Spring原理分析-Aware接口&InitializingBean

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring原理分析-Aware接口&InitializingBean相关的知识,希望对你有一定的参考价值。

参考技术A

前置文章:
一、Spring原理分析-BeanFactory与ApplicationContext
二、Spring原理分析-Bean生命周期
三、Spring原理分析-Bean后处理器
四、Spring原理分析-BeanFactory后处理器

一、Aware接口&InitializingBean
1、基础准备
2、总结
3、补充:EmbeddedValueResolverAware
二、@Autowired和@PostConstruct注解失效
1、基础准备
2、失效情形
3、失效原因
4、使用Aware接口避免失效
5、总结
补充总结

1、基础准备

注释掉AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor两个后处理器,如下:

2、总结

【A】、各类Aware及其作用:

Ⅰ BeanNameAware 注入 bean 的名字;
Ⅱ BeanFactoryAware 注入 BeanFactory 容器;
Ⅲ ApplicationContextAware 注入 ApplicationContext 容器;
Ⅳ EmbeddedValueResolverAware 解析 $。

【B】、为什么后处理器能实现的功能要通过Aware接口实现:

对比之下可以发现,原生干净的 GenericApplicationContext 容器并没有各类后处理器,需要我们手动添加才能实现拓展。
而实现这类接口,原生容器就能直接实现拓展。

3、补充:EmbeddedValueResolverAware

BeanFactoryAware与ApplicationContext类似,此处不演示。演示实现EmbeddedValueResolverAware接口,如下:

实现接口实现方法,并添加如下内容:

1、基础准备

添加ConfigurationClassPostProcessor后处理器,注册MyConfig1,如下:

此时,我们可以看到@Autowired和@PostConstruct都生效了。

2、失效情形

添加@Bean的相关内容,如下:

此时,后处理器拓展出来的注解都失效了。

3、失效原因

案例中需要被执行的 BeanFactoryPostProcessor 在 MyConfig1 配置类中。为了保证 BeanFactoryPostProcessor 能顺利执行,此时会先创建和初始化 MyConfig1 对象。但是,注册 BeanPostProcessor 的步骤并没有执行到,所以 @Autowired 这类注解并没有生效。

为了证明如上顺序,我们继续测试。

添加 MyConfig2 类,如下:

修改测试类,添加注册myConfig2,如下:

可以看到由于 MyConfig2 类中没有 BeanFactoryPostProcessor 的调用需被执行,所以其中的 BeanPostProcessor 可以正常执行到。

BeanFactoryPostProcessor 的执行顺序问题导致 BeanPostProcessor 相关配置失效。

4、使用Aware接口避免失效

实现InitializingBean、ApplicationContextAware接口,如下:

添加注册myConfig3的内容,如下:

5、总结

补充总结:

以上即为Aware接口&InitializingBean的全部内容,感谢阅读。

spring中aware接口的

一、关于spring中Aware结尾接口介绍:

Spring中提供一些Aware结尾相关接口,像是BeanFactoryAware、 BeanNameAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等。

实现这些 Aware接口的Bean在被实例化 
之后,可以取得一些相对应的资源,例如实现BeanFactoryAware的Bean在实例化后,Spring容器将会注入BeanFactory的实例,而实现ApplicationContextAware的Bean,在Bean被实例化后,将会被注入 ApplicationContext的实例等等。

通过重写setter方法,当前bean被实例化后实现相关实例的注入。

二、以BeanNameAware、ApplicationContextAware接口举例说明:

<bean name ="myContext" class="com.jsun.test.springDemo.aware.MyApplicationContext"></bean>
  • 1
//实现BeanNameAware接口,并重写setBeanName()方法,让Bean获取自己在BeanFactory配置中的名字(根据情况是id或者name)
//实现ApplicationContextAware接口,并重写setApplicationContext()方法
public class MyApplicationContext implements BeanNameAware,ApplicationContextAware{
    private String beanName;

    //注入的beanName即为MyApplicationContext在BeanFactory配置中的名字(根据情况是id或者name)
    @Override
    public void setBeanName(String beanName) {
        this.beanName = beanName;
        System.out.println("MyApplicationContext beanName:"+beanName);
    }

    @Override
    public void setApplicationContext(ApplicationContext context)
            throws BeansException {
        //通过重写的接口方法,获取spring容器实例context,进而获取容器中相关bean资源
        System.out.println(context.getBean(this.beanName).hashCode());

    }

}
    @Test
    public void testScope(){
        //单元测试再次获取bean,并输出bean的hashCode
        System.out.println(super.getBean("myContext").hashCode());
    }

上面输出结果:

信息: Loading XML bean definitions from URL [file:/E:/workspace/springDemo/target/classes/spring-ioc.xml]
MyApplicationContext beanName:myContext
1663216960
1663216960
八月 07, 2016 4:25:12 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@5531a519: startup date [Sun Aug 07 16:25:11 CST 2016]; root of context hierarchy

注意:除了通过实现Aware结尾接口获取spring内置对象,也可以通过@Autowired注解直接注入相关对象,如下: 
(如果需要用到静态方法中,如工具方法,还是采用实现接口的方式)

@Autowired
private MessageSource messageSource; 

@Autowired
private ResourceLoader resourceLoader; 

@Autowired
private ApplicationContext applicationContext;

以上是关于Spring原理分析-Aware接口&InitializingBean的主要内容,如果未能解决你的问题,请参考以下文章

[死磕 Spring 27/43] --- IOC 之 深入分析 Aware 接口

Spring Aware原理

死磕 Spring----- IOC 之 深入分析 Aware 接口

spring源码分析:Aware接口让你的bean对容器直接操作

spring中aware接口的

Spring的感知能力 Aware