一.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失效了,这是为什么呢?我们来看一下这个图片:
这是正常的执行顺序:BeanFactoryPostProcessor->BeanPostProcessor->依赖注入->初始化->执行Aware和initzationBean
这是因为当我们用@Bean注入BeanFactoryPostProcessor会导致顺序发生错乱:
我们发现因为加入了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
销毁顺序是按照以上三个顺序执行的