Aware
Spring中提供了一些以Aware结尾的接口,实现了Aware接口的bean在被初始化之后,可以获取相应资源。比如BeanNameAware之类的以Aware结尾的接口,这个接口获取的资源就是以BeanName相关的。
通过Aware接口,可以对Spring相应资源进行操作(一定要慎重,因为获取的资源可能是IOC的核心资源)。
为对Spring进行简单的扩展提供了方便的接口。
ApplicationContextAware会向实现了这个接口的Bean提供ApplicationContext,也就是IOC容器的上下文的信息。当然,实现了这个接口的Bean必须配置到bean的配置文件中去,并且由Spring的Bean容器去加载,这样才能实现这样的效果。
BeanNameAware类似,它会提供一个关于BeanName定义的这样一些内容。
接下来是个例子
配置文件
<bean id="moocApplicationContext" class="com.imooc.aware.MoocApplicationContext" ></bean>
实现类
public class MoocApplicationContext implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
System.out.println("MoocApplicationContext : " + applicationContext.getBean("moocApplicationContext"));
}
}
测试类
@RunWith(BlockJUnit4ClassRunner.class)
public class TestAware extends UnitTestBase {
public TestAware() {
super("classpath:spring-aware.xml");
}
@Test
public void testMoocApplicationContext() {
}
}
这个bean我们在配置文件里配置了。
在单元测试类里边调用这个方法(里边没有内容)。这里要注意,在调用这个方法之前会调用Before,之后会调用After。执行这个Before来创建IOC容器,After来销毁。
输出得到MOOCApplicationContext:com.imooc.aware.MoocApplicationContext@156b6b78
在初始化容器的时候调用了setApplicationContext方法,得到了当前这个Bean。
然后可以修改测试类的代码
@Test
public void testMoocApplicationContext() {
System.out.println("testMoocApplicationContext : " + super.getBean("moocApplicationContext").hashCode());
}
看看得到的是不是同一个Bean,我们可以用hashCode来区分是不是同一个。
把实现类中的代码可以稍微修改System.out.println("MoocApplicationContext : " + applicationContext.getBean("moocApplicationContext").hashCode());
这里加了一个hashCode。
输出的时候发现哈希值都是一样的,所以得到的是同一个Bean。
也就是说在测试类里边得到的Bean的实例,和Bean定义并实现ApplicationContextAware接口并覆盖它的setApplicationContext方法的时候,从这个applicationContext容器里边得到的Bean的实例是一致的。所以说我们成功的把当前的applicationContext注入到我们的方法中来,或者说成功的写到了类当中来。
这里其实是设值注入。MoocApplicationContext为A,ApplicationContext为B,applicationContext为b。在A类中有SetB的方法,这个方法是Spring的IOC容器自动调用的。给applicationContext也就是属性b进行赋值。
这里和之前写的设置注入有一点不一样。之前会有一个private B b;然后在set方法里会有this.b=b;这是为了在这个类中可以继续使用它。而这个例子里并不需要。重要的并不是有没有那样的赋值操作,而是有没有set方法。