Aware接口提供了一种内置的注入手段,可以注入BeanFactory、Application
Aware 接口用于注入一些与容器相关的信息,比如
BeanNameAware
注入bean的名字BeanFactoryAware
注入BeanFactoryApplicationContextAware
注入ApplicationContext 容器EmbeddedValueResolverAware
--帮忙解析–> ${}
BeanNameAware
注入bean的名字和ApplicationContextAware
注入ApplicationContext 容器
/**
* @author 我见青山多妩媚
* @date Create on 2022/10/6 15:22
*/
@Slf4j
public class MyBean implements BeanNameAware , ApplicationContextAware, InitializingBean {
@Override
public void setBeanName(String name) {
log.info("当前bean:{},名字叫:{}",this,name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("当前bean:{},容器是:{}",this,applicationContext);
}
}
@Slf4j
public class A06Application {
public static void main(String[] args) {
/*
1.Aware 接口用于注入一些与容器相关的信息,比如
a.BeanNameAware 注入bean的名字
b.BeanFactoryAware 注入BeanFactory
c.ApplicationContextAware 注入ApplicationContext 容器
d.EmbeddedValueResolverAware --帮忙解析--> ${}
*/
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("myBean",MyBean.class);
context.refresh();
context.close();
}
}
运行结果:
当前bean:com.spring.demo.demo06.MyBean@5bcea91b,名字叫:myBean
当前bean:com.spring.demo.demo06.MyBean@5bcea91b,容器是:org.springframework.context.support.GenericApplicationContext@21bcffb5, started on Thu Oct 06 15:36:13 CST 2022
InitializingBean接口提供的初始化手段
InitializingBean
接口/**
* @author 我见青山多妩媚
* @date Create on 2022/10/6 15:22
*/
@Slf4j
public class MyBean implements BeanNameAware , ApplicationContextAware, InitializingBean {
@Override
public void setBeanName(String name) {
log.info("当前bean:{},名字叫:{}",this,name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("当前bean:{},容器是:{}",this,applicationContext);
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("当前bean:{},初始化",this);
}
}
运行结果:
...
当前bean:com.spring.demo.demo06.MyBean@5bcea91b,初始化
可是@Autowired
注解都可以实现上面的三种方法,为什么还需要自己手动实现呢?
@Autowired
的解析是需要用到bean的后处理器,属于扩展功能我们模拟一下:
@Autowired
public void aaa(ApplicationContext applicationContext){
log.info("使用@Auwowired注入:当前bean:{},容器是:{}",this,applicationContext);
}
@PostConstruct
public void init(){
log.info("使用@PostConstruct:当前bean:{},初始化",this);
}
运行结果是没有这两个的输出的,我们在A06上加上对这两个注解的解析:
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
运行结果:
使用@Auwowired注入:当前bean:com.spring.demo.demo06.MyBean@5bfa9431,容器是:org.springframework.context.support.GenericApplicationContext@21bcffb5, started on Thu Oct 06 16:05:21 CST 2022
当前bean:com.spring.demo.demo06.MyBean@5bfa9431,名字叫:myBean
当前bean:com.spring.demo.demo06.MyBean@5bfa9431,容器是:org.springframework.context.support.GenericApplicationContext@21bcffb5, started on Thu Oct 06 16:05:21 CST 2022
使用@PostConstruct:当前bean:com.spring.demo.demo06.MyBean@5bfa9431,初始化
当前bean:com.spring.demo.demo06.MyBean@5bfa9431,初始化
/**
* @author 我见青山多妩媚
* @date Create on 2022/10/6 16:10
*/
@Configuration
@Slf4j
public class MyConfig1 {
@Autowired
public void aaa(ApplicationContext applicationContext){
log.info("注入ApplicationContext");
}
@PostConstruct
public void init(){
log.info("初始化");
}
}
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("MyConfig1",MyConfig1.class);
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
context.registerBean(CommonAnnotationBeanPostProcessor.class);
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh();
context.close();
运行结果:
注入ApplicationContext
初始化
@Bean //beanFactory后处理器
public BeanFactoryPostProcessor processor1(){
return beanFactory -> {
log.info("执行processor1");
};
}
执行processor1
此时我们的@Autowired
和 @PostConstruct
注解失效了,这是为什么?
BeanFactoryPostProcessor
的执行情况因为该例子中java配置类包含了BeanFactoryPostProcessor
的情况,因此要创建其中的BeanFactoryPostProcessor
必须提前创建java配置类,所以配置类被优先创建,包括其中注解失效的两个方法(aaa()
和 init()
),其次再去执行内置的接口,比如Aware
、InitializinBean
等,而此时的执行完之后,发现还有BeanFactoryPostProcessor
(用来解析@Autowired
和 @PostConstruct
等注解)需要解析,此时再去加载该配置,但是aaa()
和 init()
方法早就已经被配置类加载完了,此时再去加载扫描自然就扫描不到了,所以失效了。
/**
* @author 我见青山多妩媚
* @date Create on 2022/10/6 16:10
*/
@Configuration
@Slf4j
public class MyConfig2 implements InitializingBean, ApplicationContextAware {
@Override
public void afterPropertiesSet() throws Exception {
log.info("初始化");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("注入ApplicationContext");
}
@Bean //beanFactory后处理器
public BeanFactoryPostProcessor processor1(){
return beanFactory -> {
log.info("执行processor1");
};
}
}
context.registerBean("MyConfig2",MyConfig2.class);
运行结果:
注入ApplicationContext
初始化
执行processor1