Spring底层分析--6.Aware接口和Bean初始化,销毁三种方法

一.Aware接口概述:

Aware接口是容器内置的相当于bean后处理的功能,主要是他是本身就有的,一定会执行,bean后处理器在有些情况会失效,但是Aware接口不会失效

二.BeanNameAware和ApplicationContextAware

BeanNameAware该接口可以获取bean的名称。来做一些操作:

ApplicationContextAware可以获取当前bean的容器

public class BigBean implements BeanNameAware, ApplicationContextAware {

    private final static Logger log = LoggerFactory.getLogger(BigBean.class);

    @Override
    public void setBeanName(String s) {
             log.info("当前bean:"+this+"名字:"+s);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("当前bean:"+this+"的容器是:"+applicationContext);
    }
}
public class TestAware {
    public static void main(String[] args) {

        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean("bigBean", BigBean.class);

        context.refresh();

        context.close();


    }
}

运行代码:

15:02:21.282 [main] DEBUG org.springframework.context.support.GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@1990a65e
15:02:21.314 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bigBean'
15:02:21.328 [main] INFO com.jjh.component.BigBean - 当前bean:com.jjh.component.BigBean@4c9f8c13名字:bigBean
15:02:21.334 [main] INFO com.jjh.component.BigBean - 当前bean:com.jjh.component.BigBean@4c9f8c13的容器是:org.springframework.context.support.GenericApplicationContext@1990a65e, started on Tue Sep 19 15:02:21 CST 2023
15:02:21.360 [main] DEBUG org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@1990a65e, started on Tue Sep 19 15:02:21 CST 2023

可以看到,成功的获取到了bean的名称和bean的容器

二.InitializingBean

该接口是实现bean的初始化

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("当前bean:"+this+"初始化");
    }

运行:

15:10:08.704 [main] INFO com.jjh.component.BigBean - 当前bean:com.jjh.component.BigBean@be64738名字:bigBean
15:10:08.708 [main] INFO com.jjh.component.BigBean - 当前bean:com.jjh.component.BigBean@be64738的容器是:org.springframework.context.support.GenericApplicationContext@1990a65e, started on Tue Sep 19 15:10:08 CST 2023
15:10:08.709 [main] INFO com.jjh.component.BigBean - 当前bean:com.jjh.component.BigBean@be64738初始化

三.@Atuowired失效情况

1.举例

在有些情况下,@Autowired注解会失效,下面我们来举一个例子:

我们在配置类中通过@Autowired注入ApplicatiionContext:

@Configuration
public class AwareConfig {

    private final static Logger log = LoggerFactory.getLogger(AwareConfig.class);

    @Autowired
    public void setApplicationContext(ApplicationContext context){
        log.info("@Autowired生效");
    }


    @PostConstruct
    public void init(){
        log.info("初始化");
    }



     @Bean
    public BeanFactoryPostProcessor beanFactoryPostProcessor(){
        return configurableListableBeanFactory -> log.info("创建BeanFactoryPostProcessor");
     }
}

我们在这个类中添加了beanFactory后处理器,

然后我们来获取这个bean,看看能否能够执行@Autowired注解注入:

15:45:46.722 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'awareConfig'
15:45:46.725 [main] INFO org.springframework.context.annotation.ConfigurationClassEnhancer - @Bean method AwareConfig.beanFactoryPostProcessor is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
15:45:46.732 [main] INFO com.jjh.configure.AwareConfig - 创建BeanFactoryPostProcessor
15:45:46.732 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor'
15:45:46.752 [main] DEBUG org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@1990a65e, started on Tue Sep 19 15:45:46 CST 2023

 2.原理分析

我们发现日志并没有被打印,说明@Autowired失效了,这是为什么呢?我们来看一下这个图片:

048151737e2b4233a461c020d2cf2747.png

 

 这是正常的执行顺序:BeanFactoryPostProcessor->BeanPostProcessor->依赖注入->初始化->执行Aware和initzationBean

这是因为当我们用@Bean注入BeanFactoryPostProcessor会导致顺序发生错乱:

ea5b797d249f4abcbdd25a9e4c2af1b0.png

我们发现因为加入了BeanPostProcessor,这是是用工厂方法来创建的,于是必须先创建AwareConfig对象,于是导致了顺序的改变,创建对象时,还没有注入Bean后处理器,也就导致了@AutoWired注解失效,

3.解决方法:

我们使用Aware接口,不使用@Autowired,就能解决该问题:

@Configuration
public class AwareConfig2 implements BeanNameAware, ApplicationContextAware, InitializingBean {

    private final static Logger log = LoggerFactory.getLogger(AwareConfig2.class);

    @Override
    public void setBeanName(String s) {
             log.info("当前bean:"+this+"名字:"+s);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("当前bean:"+this+"的容器是:"+applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("当前bean:"+this+"初始化");
    }

    @Bean
    public BeanFactoryPostProcessor beanFactoryPostProcessor(){
        return configurableListableBeanFactory -> log.info("创建BeanFactoryPostProcessor");
    }
}

我们在运行一下看看是否能顺利执行:

16:02:48.500 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'awareConfig2'
16:02:48.501 [main] INFO com.jjh.configure.AwareConfig2 - 当前bean:com.jjh.configure.AwareConfig2$$EnhancerBySpringCGLIB$$24f68fde@3ee37e5a名字:awareConfig2
16:02:48.505 [main] INFO com.jjh.configure.AwareConfig2 - 当前bean:com.jjh.configure.AwareConfig2$$EnhancerBySpringCGLIB$$24f68fde@3ee37e5a的容器是:org.springframework.context.support.GenericApplicationContext@1990a65e, started on Tue Sep 19 16:02:48 CST 2023
16:02:48.505 [main] INFO com.jjh.configure.AwareConfig2 - 当前bean:com.jjh.configure.AwareConfig2$$EnhancerBySpringCGLIB$$24f68fde@3ee37e5a初始化
16:02:48.508 [main] INFO org.springframework.context.annotation.ConfigurationClassEnhancer - @Bean method AwareConfig2.beanFactoryPostProcessor is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
16:02:48.515 [main] INFO com.jjh.configure.AwareConfig2 - 创建BeanFactoryPostProcessor
16:02:48.516 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor'
16:02:48.532 [main] DEBUG org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext@1990a65e, started on Tue Sep 19 16:02:48 CST 2023

进程已结束,退出代码0

我们可以看到成功的执行了方法

4.总结:

Aware接口是Spring内置的可以和@Autowired和@PostCustrut等效的形式,

很多spirng内部类都使用Aware接口

四.bean的初始化和销毁三种方法

1.初始化三种方法:

public class Bean5 implements InitializingBean {

    private final static Logger log = LoggerFactory.getLogger(Bean5.class);

    @PostConstruct
    public void postConstruct(){
        log.info("初始化1");
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("初始化2");
    }

    public void init(){
        log.info("初始化3");
    }
}

(1)@PostConstruct注解

(2)实现InitializingBean接口

(3)在@Bean上指定初始方法名称

@SpringBootApplication
public class InitAndDestroyApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(InitAndDestroyApplication.class, args);

        context.close();
    }

    @Bean(initMethod = "init")
    public Bean5 bean5(){
        return new Bean5();
    }

}

运行:

2023-09-19 16:25:56.927  INFO 4392 --- [           main] com.jjh.component.Bean5                  : 初始化1
2023-09-19 16:25:56.928  INFO 4392 --- [           main] com.jjh.component.Bean5                  : 初始化2
2023-09-19 16:25:56.928  INFO 4392 --- [           main] com.jjh.component.Bean5                  : 初始化3
2023-09-19 16:25:56.978  INFO 4392 --- [           main] com.jjh.InitAndDestroyApplication        : Started 

执行顺序就是按照以上三个顺序

2.销毁三种方法

public class Bean6 implements DisposableBean {

    private final static Logger log = LoggerFactory.getLogger(Bean6.class);

    @PreDestroy
    public void preDestroy(){
        log.info("销毁1");
    }


    @Override
    public void destroy() throws Exception {
        log.info("销毁2");
    }

    public void destroyed(){
        log.info("销毁3");
    }
}

(1)@PreDestroy注解

(2)实现DisposableBean接口

  (3)@Bean指定销毁方法

    @Bean(destroyMethod = "destroyed")
    public Bean6 bean6(){
        return new Bean6();
    }

运行:

2023-09-19 16:31:44.379  INFO 17956 --- [           main] com.jjh.InitAndDestroyApplication        : Started InitAndDestroyApplication in 0.405 seconds (JVM running for 1.13)
2023-09-19 16:31:44.382  INFO 17956 --- [           main] com.jjh.component.Bean6                  : 销毁1
2023-09-19 16:31:44.382  INFO 17956 --- [           main] com.jjh.component.Bean6                  : 销毁2
2023-09-19 16:31:44.382  INFO 17956 --- [           main] com.jjh.component.Bean6                  : 销毁3

销毁顺序是按照以上三个顺序执行的

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值