Spring源码(2)BeanFactory工厂后置处理器、Bean的后置处理器、ApplicationContext容器、Bean的生命周期
1、目标
本文的主要目标是学习BeanFactory工厂后置处理器、Bean的后置处理器、ApplicationContext容器、Bean的生命周期
2、BeanFactory
2.1 BeanFactory工厂后置处理器
@SpringBootApplication
@Log4j2
public class SpringBootDemoApplication {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
// BeanFactory对象注册BeanDefinition对象
beanFactory.registerBeanDefinition("config", beanDefinition);
// BeanFactory对象添加后置处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// 执行BeanFactoryPostProcessor后置处理器的postProcessBeanFactory方法才会将@Bean注解的对象注入到容器中
for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values()) {
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
}
// 输出注册的bean的名字
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
@Configuration
static class Config {
@Bean
public Bean01 bean01() {
return new Bean01();
}
@Bean
public Bean02 bean02() {
return new Bean02();
}
}
static class Bean01 {
@Autowired
private Bean02 bean02;
}
static class Bean02 {
}
}
DefaultListableBeanFactory是默认的BeanFactory对象,BeanFactory对象可以注册BeanDefinition对象
BeanFactoryPostProcessor这是bean工厂的后置处理器,通过postProcessBeanFactory方法可以添加一些bean对象的定义
输出结果是:
可以看到,BeanFactory容器中包含了config、bean01、bean02和后置处理器等对象
internalAutowiredAnnotationProcessor后置处理器是bean工厂的后置处理器,专门用来处理器@Autowired注解的
internalCommonAnnotationProcessor后置处理器是bean工厂的后置处理器,专门用来处理@Resource注解的
2.2 Bean的后置处理器
2.2.1 添加Bean的后置处理器可以依赖注入成功
Bean01 bean01 = beanFactory.getBean(Bean01.class);
System.out.println("bean01 = " + bean01);
Bean02 bean02 = beanFactory.getBean(Bean02.class);
System.out.println("bean02 = " + bean02);
bean02 = beanFactory.getBean(Bean01.class).getBean02(); //为null说明依赖注入失败了
System.out.println("bean02 = " + bean02);
获取Bean01对象中依赖注入的Bean02对象,会返回null,因为没有将bean的后置处理器放到添加到BeanFactory中
没有依赖注入bean02对象
// 执行BeanPostProcessor后置处理器的方法会对bean的生命周期提供扩展,比如对@Autowired和@Resource注解等
Collection<BeanPostProcessor> values = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
values.forEach(beanFactory::addBeanPostProcessor);
执行BeanPostProcessor后置处理器的addBeanPostProcessor方法会对bean的生命周期提供扩展
添加了在bean01对象中的bean02对象会依赖注入成功
2.2.2 @Autowired和@Resource注解解析的优先级顺序
希望看到@Autowired和@Resource注解依赖注入的顺序,可以打印bean的后置处理器BeanPostProcessor
// 执行BeanPostProcessor后置处理器的方法会对bean的生命周期提供扩展,比如对@Autowired和@Resource注解等
Collection<BeanPostProcessor> values = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
values.forEach(beanPostProcessor -> {
System.out.println("beanPostProcessor = " + beanPostProcessor);
beanFactory.addBeanPostProcessor(beanPostProcessor);
});
遍历并打印所有的BeanPostProcessor对象
可以看到Autowired注解的bean后置处理器比Resource注解的bean后置处理器优先执行,因此如果这两个注解同时存在的话会优先解析@Autowired注解
// 执行BeanPostProcessor后置处理器的方法会对bean的生命周期提供扩展,比如对@Autowired和@Resource注解等
Collection<BeanPostProcessor> values = beanFactory.getBeansOfType(BeanPostProcessor.class).values();
values.stream().sorted(beanFactory.getDependencyComparator()).forEach(beanPostProcessor -> {
System.out.println("beanPostProcessor = " + beanPostProcessor);
beanFactory.addBeanPostProcessor(beanPostProcessor);
});
这个根据Stream流的sorted进行排序,是根据BeanFactory对象的getDependencyComparator方法进行排序
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory)方法是设置BeanFactory对象的依赖比较器
AutowiredAnnotationBeanPostProcessor这个bean的后置处理器是依赖注入@Autowired注解的bean对象,它的order设置成Integer的最大值减去2
CommonAnnotationBeanPostProcessor这个bean的后置处理器是依赖注入@Resource注解的bean对象,它的order设置成Integer的最大值减去3
order的值越小,优先级越高
可以看到,根据order进行排序,CommonAnnotationBeanPostProcessor的@Resource注解解析的bean对象优先级比AutowiredAnnotationBeanPostProcessor的@Autowried注解解析的bean对象的优先级更高
2.3 加载容器中的对象
System.out.println("==========================");
Bean01 bean01 = beanFactory.getBean(Bean01.class);
System.out.println("bean01 = " + bean01);
Bean02 bean02 = beanFactory.getBean(Bean02.class);
System.out.println("bean02 = " + bean02);
bean02 = beanFactory.getBean(Bean01.class).getBean02(); //为null说明依赖注入失败了
System.out.println("bean02 = " + bean02);
默认是懒加载的,getBean用到这个对象的时候才会执行构造器
调用getBean方法才会执行构造器
// 实例化单例对象
beanFactory.preInstantiateSingletons();
System.out.println("==========================");
Bean01 bean01 = beanFactory.getBean(Bean01.class);
System.out.println("bean01 = " + bean01);
Bean02 bean02 = beanFactory.getBean(Bean02.class);
System.out.println("bean02 = " + bean02);
bean02 = beanFactory.getBean(Bean01.class).getBean02(); //为null说明依赖注入失败了
System.out.println("bean02 = " + bean02);
beanFactory.preInstantiateSingletons()方法会初始化容器中的单例对象
默认情况下是懒加载的,beanFactory.preInstantiateSingletons()方法会初始化容器中的单例对象
2.4 总结
因此,BeanFactory对象不会主动调用BeanFactory工厂的后置处理器,不会主动调用Bean的后置处理器,不会主动初始化单例对象,不会解析#{}和${}
3、ApplicationContext
AnnotationConfigServletWebServerApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
AnnotationConfigServletWebServerApplicationContex是一个基于注解配置的web服务器的容器applicationContext
@Configuration
static class WebConfig {
// 配置内嵌容器
@Bean
public ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
// 注册DispatcherServlet到Tomcat服务器
@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
}
// Controller接口
@Bean("/hello")
public Controller controller() {
return (httpServletRequest, httpServletResponse) -> {
httpServletResponse.getWriter().println("hello");
return null;
};
}
}
WebConfig是一个配置类,它在容器中创建了内嵌容器TomcatServletWebServerFactory,它创建了DispatcherServlet对象,它创建了DispatcherServletRegistrationBean对象用来注册DispatcherServlet对象到Tomcat服务器,还创建了一个Controller,这个Controller是一个接口,它在springframework.web.servlet.mvc包下,@Bean上写上/hello表示请求路径是/hello
浏览器输入:localhost:8080/hello,浏览器会返回hello
问题:启动服务失败
启动SpringBoot时发现DispatcherServletRegistrationBean有多个Bean实例,因此容器不知道选择哪个,因此可以使用@Primary注解指定相同类型的多个Bean对象优先使用哪个Bean对象并注入到容器中
4、Bean的生命周期
4.1 Bean的生命周期
Bean的生命周期包括:
构造方法实例化、依赖注入、初始化、销毁
@Component
@Log4j2
public class LifeCycleBean {
public LifeCycleBean() {
log.info("LifeCycleBean构造方法执行");
}
@Autowired
public void autowire(I18nMsgService i18nMsgService) {
System.out.println(i18nMsgService.toString());
log.info("LifeCycleBean依赖注入对象");
}
@PostConstruct
public void init() {
log.info("LifeCycleBean初始化");
}
@PreDestroy
public void destroy() {
log.info("LifeCycleBean销毁方法");
}
}
用@Component注解将LifeCycleBean对象注入到容器中,构造方法,用@Autowired注解依赖注入对象,用@PostConstruct注解实现初始化方法,用@PreDestroy注解实现销毁方法,方法的入参可以传入容器中的Bean对象
Bean的生命周期顺序是执行构造方法实例化、依赖注入方法、初始化方法、销毁方法
和Bean的生命周期相关的有Bean的后置处理器
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if("lifeCycleBean".equals(beanName)) {
System.out.println(beanName + "对象构造方法执行之前(实例化之前)");
}
// 修改返回的对象,如果返回null则保持原对象不变
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if("lifeCycleBean".equals(beanName)) {
System.out.println(beanName + "对象构造器方法执行之后(实例化之后)");
}
// 如果返回false则会跳过依赖注入阶段
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if("lifeCycleBean".equals(beanName)) {
System.out.println(beanName + "对象依赖注入执行,解析@Autowired、@Resource、@Value");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("lifeCycleBean".equals(beanName)) {
System.out.println(beanName + "对象的初始化方法之前执行,解析@PostConstruct, @ConfigurationProperties注解");
}
// 修改返回的对象,如果返回null则保持原对象不变
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("lifeCycleBean".equals(beanName)) {
System.out.println(beanName + "对象的初始化方法之后执行,可以创建代理对象用来增强");
}
// 修改返回的对象,如果返回null则保持原对象不变
return null;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if("lifeCycleBean".equals(beanName)) {
System.out.println(beanName + "对象的销毁方法之前执行");
}
}
}
InstantiationAwareBeanPostProcessor和DestructionAwareBeanPostProcessor接口都继承了BeanPostProcessor接口
重写了实例化之前和之后的方法,重写了依赖注入之前的方法,重写了初始化之前和之后的方法,重写了销毁之前的方法
在LifeCycleBean对象的构造方法之前和之后分别打印,在依赖注入方法之前打印,在初始化方法之前和之后分别打印,在销毁方法之前打印
4.2 模板方法模式
模拟getBean方法,bean的生命周期中后置处理器用到模板方法模式
public class MyBeanFactory {
@Test
public void f1() {
MyBeanFactory myBeanFactory = new MyBeanFactory();
myBeanFactory.addBeanPostProcessor(bean -> System.out.println("bean后置处理器解析@Autowired注解"));
myBeanFactory.addBeanPostProcessor(bean -> System.out.println("bean后置处理器解析@Resource注解"));
Object bean = myBeanFactory.getBean();
System.out.println("bean = " + bean);
}
public Object getBean() {
Object bean = new Object();
System.out.println("bean构造方法执行");
System.out.println("bean依赖注入执行");
// 抽象方法模式中变化的部分放在接口的方法上
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
beanPostProcessor.inject(bean);
}
System.out.println("bean初始化方法执行");
System.out.println("bean销毁方法执行");
return bean;
}
// 持有变化部分的接口集合
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
beanPostProcessorList.add(beanPostProcessor);
}
public interface BeanPostProcessor {
public abstract void inject(Object bean);
}
}
模板方法模式是将变化的部分封装成一个接口或者抽象类,包含抽象方法,持有接口或者抽象类的List集合,用add方法新增持有的接口或者抽象类
模板方法模式可以执行Bean的生命周期
5、Bean的后置处理器
static class Bean1 {
private Bean2 bean2;
@Autowired
public void setBean2(Bean2 bean2) {
System.out.println("@Autowired注解生效");
this.bean2 = bean2;
}
private Bean3 bean3;
@Resource
public void setBean3(Bean3 bean3) {
System.out.println("@Resource注解生效");
this.bean3 = bean3;
}
@Autowired
public void getServerPort(@Value("${server.port}") String port) {
System.out.println("@Value生效,port = " + port);
}
@PostConstruct
public void init() {
System.out.println("@PostConstruct注解生效");
}
@PreDestroy
public void destroy() {
System.out.println("@PreDestroy注解生效");
}
}
static class Bean2 {
}
static class Bean3 {
}
定义Bean1、Bean2、Bean3等Bean对象,其中@Autowired修改的方法入参可以传入容器中的Bean对象,如果是字符串就用@Value注入
// GenericApplicationContext对象注册Bean对象
GenericApplicationContext genericApplicationContext = new GenericApplicationContext();
genericApplicationContext.registerBean("bean1", Bean1.class);
genericApplicationContext.registerBean("bean2", Bean2.class);
genericApplicationContext.registerBean("bean3", Bean3.class);
// 注册后置处理器对象
// 设置@Value注入的对象
genericApplicationContext.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 解析@Autowired @Value注解
genericApplicationContext.registerBean(AutowiredAnnotationBeanPostProcessor.class);
// 解析@Resource @PostConstruct @PreDestroy注解
genericApplicationContext.registerBean(CommonAnnotationBeanPostProcessor.class);
// 解析@ConfigurationProperties注解
ConfigurationPropertiesBindingPostProcessor.register(genericApplicationContext.getDefaultListableBeanFactory());
// 初始化容器
genericApplicationContext.refresh();
// 销毁容器
genericApplicationContext.close();
GenericApplicationContext容器对象可以通过registerBean方法注册Bean对象,可以注册BeanPostProcessor后置处理器对象,可以通过refresh方法初始化容器,通过close方法销毁容器
先处理@Resource的后置处理器,然后处理@Autowired的后置处理器,因为@Resource的后置处理器的优先级更高
原文地址:https://blog.csdn.net/weixin_43823462/article/details/141751165
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!