spring中提供一些aware相关接口,像是beanfactoryaware、 applicationcontextaware、resourceloaderaware、servletcontextaware等等,实现这些 aware接口的bean在被初始之后,可以取得一些相对应的资源,例如实现beanfactoryaware的bean在初始后,spring容器将会注入beanfactory的实例,而实现applicationcontextaware的bean,在bean被初始后,将会被注入 applicationcontext的实例等等。
bean取得beanfactory、applicationcontextaware的实例目的是什么,一般的目的就是要取得一些档案资源的存取、相 关讯息资源或是那些被注入的实例所提供的机制,例如applicationcontextaware提供了publishevent()方法,可以支持基于observer模式的事件传播机制。
applicationcontextaware接口的定义如下:
applicationcontextaware.java
public interface applicationcontextaware {
void setapplicationcontext(applicationcontext context);
}
我们这边示范如何透过实现applicationcontextaware注入applicationcontext来实现事件传播,首先我们的hellobean如下:
hellobean.java
package onlyfun.caterpillar;
import org.springframework.context.*;
public class hellobean implements applicationcontextaware {
private applicationcontext applicationcontext;
private string helloword = "hello!world!";
public void setapplicationcontext(applicationcontext context) {
this.applicationcontext = context;
}
public void sethelloword(string helloword) {
this.helloword = helloword;
}
public string gethelloword() {
applicationcontext.publishevent(
new propertygettedevent("[" helloword "] is getted"));
return helloword;
}
}
applicationcontext会由spring容器注入,publishevent()方法需要一个继承applicationevent的对象,我们的propertygettedevent继承了applicationevent,如下:
propertygettedevent.java
package onlyfun.caterpillar;
import org.springframework.context.*;
public class propertygettedevent extends applicationevent {
public propertygettedevent(object source) {
super(source);
}
}
当applicationcontext执行publishevent()后,会自动寻找实现applicationlistener接口的对象并通知其发生对应事件,我们实现了propertygettedlistener如下:
prppertygettedlistener.java
package onlyfun.caterpillar;
import org.springframework.context.*;
public class propertygettedlistener implements applicationlistener {
public void onapplicationevent(applicationevent event) {
system.out.println(event.getsource().tostring());
}
}
listener必须被实例化,这我们可以在bean定义档中加以定义:
hello!justin!
我们写一个测试程序来测测事件传播的运行:
test.java
package onlyfun.caterpillar;
import org.springframework.context.*;
import org.springframework.context.support.*;
public class test {
public static void main(string[] args) {
applicationcontext context = new classpathxmlapplicationcontext("bean.xml");
hellobean hello = (hellobean) context.getbean("hellobean");
system.out.println(hello.gethelloword());
}
}
执行结果会如下所示:
log4j:warn no appenders could be found for logger
(org.springframework.beans.factory.xml.xmlbeandefinitionreader).
log4j:warn please initialize the log4j system properly.
org.springframework.context.support.classpathxmlapplicationcontext:
displayname=[org.springframework.context.support.classpathxmlapplicationcontext;
hashcode=33219526]; startup date=[fri oct 29 10:56:35 cst 2004];
root of applicationcontext hierarchy
[hello!justin!] is getted
hello!justin!
以上是以实现事件传播来看看实现aware接口取得对应对象后,可以进行的动作,同样的,您也可以实现resourceloaderaware接口:
resourceloaderaware.java
public interface resourceloaderaware {
void setresourceloader(resourceloader loader);
}
实现resourceloader的bean就可以取得resourceloader的实例,如此就可以使用它的getresource()方法,这对于必须存取档案资源的bean相当有用。
基本上,spring虽然提供了这些aware相关接口,然而bean上若实现了这些界面,就算是与spring发生了依赖,从另一个角度来看,虽然您可以直接在bean上实现这些接口,但您也可以透过setter来完成依赖注入,例如:
hellobean.java
package onlyfun.caterpillar;
import org.springframework.context.*;
public class hellobean {
private applicationcontext applicationcontext;
private string helloword = "hello!world!";
public void setapplicationcontext(applicationcontext context) {
this.applicationcontext = context;
}
public void sethelloword(string helloword) {
this.helloword = helloword;
}
public string gethelloword() {
applicationcontext.publishevent(new propertygettedevent("[" helloword "] is getted"));
return helloword;
}
}
注意这次我们并没有实现applicationcontextaware,我们在程序中可以自行注入applicationcontext实例:
applicationcontext context = new classpathxmlapplicationcontext("bean.xml");
hellobean hello = (hellobean) context.getbean("hellobean");
hello.setapplicationcontext(context);
system.out.println(hello.gethelloword());
就bean而言,降低了对spring的依赖,可以比较容易从现有的框架中脱离。