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);}}@Configurationstatic class Config {@Beanpublic Bean01 bean01() {return new Bean01();}@Beanpublic Bean02 bean02() {return new Bean02();}}static class Bean01 {@Autowiredprivate 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 {// 配置内嵌容器@Beanpublic ServletWebServerFactory servletWebServerFactory() {return new TomcatServletWebServerFactory();}@Beanpublic DispatcherServlet dispatcherServlet() {return new DispatcherServlet();}// 注册DispatcherServlet到Tomcat服务器@Beanpublic 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构造方法执行");}@Autowiredpublic void autowire(I18nMsgService i18nMsgService) {System.out.println(i18nMsgService.toString());log.info("LifeCycleBean依赖注入对象");}@PostConstructpublic void init() {log.info("LifeCycleBean初始化");}@PreDestroypublic void destroy() {log.info("LifeCycleBean销毁方法");}}
用@Component注解将LifeCycleBean对象注入到容器中,构造方法,用@Autowired注解依赖注入对象,用@PostConstruct注解实现初始化方法,用@PreDestroy注解实现销毁方法,方法的入参可以传入容器中的Bean对象
Bean的生命周期顺序是执行构造方法实例化、依赖注入方法、初始化方法、销毁方法
和Bean的生命周期相关的有Bean的后置处理器
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if("lifeCycleBean".equals(beanName)) {System.out.println(beanName + "对象构造方法执行之前(实例化之前)");}// 修改返回的对象,如果返回null则保持原对象不变return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if("lifeCycleBean".equals(beanName)) {System.out.println(beanName + "对象构造器方法执行之后(实例化之后)");}// 如果返回false则会跳过依赖注入阶段return true;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if("lifeCycleBean".equals(beanName)) {System.out.println(beanName + "对象依赖注入执行,解析@Autowired、@Resource、@Value");}return pvs;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if("lifeCycleBean".equals(beanName)) {System.out.println(beanName + "对象的初始化方法之前执行,解析@PostConstruct, @ConfigurationProperties注解");}// 修改返回的对象,如果返回null则保持原对象不变return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if("lifeCycleBean".equals(beanName)) {System.out.println(beanName + "对象的初始化方法之后执行,可以创建代理对象用来增强");}// 修改返回的对象,如果返回null则保持原对象不变return null;}@Overridepublic 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 {@Testpublic 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;@Autowiredpublic void setBean2(Bean2 bean2) {System.out.println("@Autowired注解生效");this.bean2 = bean2;}private Bean3 bean3;@Resourcepublic void setBean3(Bean3 bean3) {System.out.println("@Resource注解生效");this.bean3 = bean3;}@Autowiredpublic void getServerPort(@Value("${server.port}") String port) {System.out.println("@Value生效,port = " + port);}@PostConstructpublic void init() {System.out.println("@PostConstruct注解生效");}@PreDestroypublic 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的后置处理器的优先级更高