• Spring原理学习(二)Bean的生命周期与Bean后处理器


    一、Bean的生命周期

    学习目标:

    1. Spring bean 生命周期各个阶段
    2. 模板设计模式

    Bean生命周期

    1、代码演示

    主程序类

    1. @SpringBootApplication
    2. public class A03Application {
    3. public static void main(String[] args) {
    4. ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
    5. context.close();
    6. }
    7. }

     实体类

    1. @Component
    2. public class LifeCycleBean {
    3. private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);
    4. public LifeCycleBean() {
    5. log.debug("构造");
    6. }
    7. @Autowired
    8. //注入环境变量JAVA_HOME的值
    9. public void autowire(@Value("${JAVA_HOME}") String home) {
    10. log.debug("依赖注入: {}", home);
    11. }
    12. @PostConstruct
    13. public void init() {
    14. log.debug("初始化");
    15. }
    16. @PreDestroy
    17. public void destroy() {
    18. log.debug("销毁");
    19. }
    20. }

    启动主程序类,结果:

    1. com.itheima.a03.LifeCycleBean - 构造
    2. [DEBUG] 09:37:46.542 [main] com.itheima.a03.LifeCycleBean - 依赖注入: D:\developer_tools\jdk\1.8.0_131
    3. [DEBUG] 09:37:46.545 [main] com.itheima.a03.LifeCycleBean - 初始化
    4. [DEBUG] 09:37:48.370 [main] com.itheima.a03.LifeCycleBean - 销毁

     使用Bean后处理器在前后提供扩展

    1. @Component
    2. public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    3. private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);
    4. @Override
    5. public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
    6. if (beanName.equals("lifeCycleBean"))
    7. log.debug("<<<<<< 实例化之前执行, 这里返回的对象会替换掉原本的 bean");
    8. //返回null则保持原有对象不变
    9. return null;
    10. }
    11. @Override
    12. public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    13. if (beanName.equals("lifeCycleBean")) {
    14. log.debug("<<<<<< 实例化之后执行, 这里如果返回 false 会跳过依赖注入阶段");
    15. //return false;
    16. }
    17. //返回 true 则继续依赖注入
    18. return true;
    19. }
    20. @Override
    21. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    22. if (beanName.equals("lifeCycleBean"))
    23. log.debug("<<<<<< 依赖注入阶段执行, 如 @Autowired、@Value、@Resource");
    24. return pvs;
    25. }
    26. @Override
    27. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    28. if (beanName.equals("lifeCycleBean"))
    29. log.debug("<<<<<< 初始化之前执行, 这里返回的对象会替换掉原本的 bean, 如 @PostConstruct、@ConfigurationProperties");
    30. return bean;
    31. }
    32. @Override
    33. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    34. if (beanName.equals("lifeCycleBean"))
    35. log.debug("<<<<<< 初始化之后执行, 这里返回的对象会替换掉原本的 bean, 如代理增强");
    36. return bean;
    37. }
    38. @Override
    39. public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
    40. if (beanName.equals("lifeCycleBean"))
    41. log.debug("<<<<<< 销毁之前执行, 如 @PreDestroy");
    42. }
    43. }

    创建前后的增强

    • postProcessBeforeInstantiation

      • 这里返回的对象若不为 null 会替换掉原本的 bean,并且仅会走 postProcessAfterInitialization 流程

    • postProcessAfterInstantiation

      • 这里如果返回 false 会跳过依赖注入阶段

    依赖注入前的增强

    • postProcessProperties

      • 如 @Autowired、@Value、@Resource

    初始化前后的增强

    • postProcessBeforeInitialization

      • 这里返回的对象会替换掉原本的 bean

      • 如 @PostConstruct、@ConfigurationProperties

    • postProcessAfterInitialization

      • 这里返回的对象会替换掉原本的 bean

      • 如代理增强

    销毁之前的增强

    • postProcessBeforeDestruction

      • 如 @PreDestroy

    结果:

    1. com.itheima.a03.MyBeanPostProcessor - <<<<<< 实例化之前执行, 这里返回的对象会替换掉原本的 bean
    2. com.itheima.a03.LifeCycleBean - 构造
    3. com.itheima.a03.MyBeanPostProcessor - <<<<<< 实例化之后执行, 这里如果返回 false 会跳过依赖注入阶段
    4. com.itheima.a03.MyBeanPostProcessor - <<<<<< 依赖注入阶段执行, 如 @Autowired@Value@Resource
    5. com.itheima.a03.LifeCycleBean - 依赖注入: D:\developer_tools\jdk\1.8.0_131
    6. com.itheima.a03.MyBeanPostProcessor - <<<<<< 初始化之前执行, 这里返回的对象会替换掉原本的 bean, 如 @PostConstruct@ConfigurationProperties
    7. com.itheima.a03.LifeCycleBean - 初始化
    8. com.itheima.a03.MyBeanPostProcessor - <<<<<< 初始化之后执行, 这里返回的对象会替换掉原本的 bean, 如代理增强
    9. com.itheima.a03.MyBeanPostProcessor - <<<<<< 销毁之前执行, 如 @PreDestroy
    10. com.itheima.a03.LifeCycleBean - 销毁

    2、模板方法设计模式

    1. public class TestMethodTemplate {
    2. public static void main(String[] args) {
    3. MyBeanFactory beanFactory = new MyBeanFactory();
    4. beanFactory.getBean();
    5. }
    6. static class MyBeanFactory {
    7. public Object getBean() {
    8. Object bean = new Object();
    9. System.out.println("构造 " + bean);
    10. System.out.println("依赖注入 " + bean);
    11. System.out.println("初始化 " + bean);
    12. return bean;
    13. }
    14. }
    15. }

    场景:刚开始只实现了基本的功能,后面需要对依赖注入的功能进行扩展, 需要支持@Autowired的解析,在原代码上去修改的话扩展性不好, 如果后面需要继续支持 @Resource注解解析,又去原代码修改,这种做法不是很好。

    使用模板模式:固定不变的形成方法的主干,变化的部分抽象成接口,Spring底层也是这样做的,这里只是简单模拟了一下。

    1. public class TestMethodTemplate {
    2. public static void main(String[] args) {
    3. MyBeanFactory beanFactory = new MyBeanFactory();
    4. beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
    5. beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));
    6. beanFactory.getBean();
    7. }
    8. static class MyBeanFactory {
    9. public Object getBean() {
    10. Object bean = new Object();
    11. System.out.println("构造 " + bean);
    12. System.out.println("依赖注入 " + bean);
    13. //实现功能的扩展
    14. for (BeanPostProcessor processor : processors) {
    15. processor.inject(bean);
    16. }
    17. System.out.println("初始化 " + bean);
    18. return bean;
    19. }
    20. //后处理器列表
    21. private List processors = new ArrayList();
    22. //添加后处理器
    23. public void addBeanPostProcessor(BeanPostProcessor postProcessor){
    24. processors.add(postProcessor);
    25. }
    26. }
    27. static interface BeanPostProcessor {
    28. public void inject(Object bean);//对依赖注入阶段的扩展
    29. }
    30. }

    3、bean 后处理器的排序

    1. public class TestProcessOrder {
    2. public static void main(String[] args) {
    3. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    4. //注册处理器
    5. AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
    6. List list = new ArrayList(Arrays.asList(new P1(), new P2(), new P3(), new P4(), new P5()));
    7. //通过AnnotationAwareOrderComparator比较
    8. list.sort(beanFactory.getDependencyComparator());
    9. list.forEach(processor->{
    10. //对bean执行处理器
    11. processor.postProcessBeforeInitialization(new Object(), "");
    12. });
    13. }
    14. @Order(1)
    15. static class P1 implements BeanPostProcessor {
    16. private static final Logger log = LoggerFactory.getLogger(P1.class);
    17. @Override
    18. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    19. log.debug("postProcessBeforeInitialization @Order(1)");
    20. return bean;
    21. }
    22. }
    23. @Order(2)
    24. static class P2 implements BeanPostProcessor {
    25. private static final Logger log = LoggerFactory.getLogger(P2.class);
    26. @Override
    27. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    28. log.debug("postProcessBeforeInitialization @Order(2)");
    29. return bean;
    30. }
    31. }
    32. static class P3 implements BeanPostProcessor, PriorityOrdered {
    33. private static final Logger log = LoggerFactory.getLogger(P3.class);
    34. @Override
    35. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    36. log.debug("postProcessBeforeInitialization PriorityOrdered");
    37. return bean;
    38. }
    39. @Override
    40. public int getOrder() {
    41. return 100;
    42. }
    43. }
    44. static class P4 implements BeanPostProcessor, Ordered {
    45. private static final Logger log = LoggerFactory.getLogger(P4.class);
    46. @Override
    47. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    48. log.debug("postProcessBeforeInitialization Ordered");
    49. return bean;
    50. }
    51. @Override
    52. public int getOrder() {
    53. return 0;
    54. }
    55. }
    56. static class P5 implements BeanPostProcessor {
    57. private static final Logger log = LoggerFactory.getLogger(P5.class);
    58. @Override
    59. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    60. log.debug("postProcessBeforeInitialization");
    61. return bean;
    62. }
    63. }
    64. }

    结果

    1. com.itheima.a03.TestProcessOrder$P3 - postProcessBeforeInitialization PriorityOrdered
    2. com.itheima.a03.TestProcessOrder$P4 - postProcessBeforeInitialization Ordered
    3. com.itheima.a03.TestProcessOrder$P1 - postProcessBeforeInitialization @Order(1)
    4. com.itheima.a03.TestProcessOrder$P2 - postProcessBeforeInitialization @Order(2)
    5. com.itheima.a03.TestProcessOrder$P5 - postProcessBeforeInitialization

    debug发现 beanFactory.getDependencyComparator() 的结果是 AnnotationAwareOrderComparator,来看看这个比较器的底层原理,更好的理解底层如何排序。

    4、AnnotationAwareOrderComparator原理

    1)AnnotationAwareOrderComparator是什么?

    AnnotationAwareOrderComparator是Spring内部的核心排序组件,通过这个类,可以对实现了PriorityOrdered、Ordered以及被@Order注解修饰的类进行统一的排序。

    2)主要排序组件类介绍

    • OrderComparator:排序器基类,实现了Comparator,排序规则仅支持PriorityOrdered、Ordered,不支持@Order。
    • AnnotationAwareOrderComparator:继承自OrderComparator,在OrderComparator排序的基础上,增加了对排序类的@Order注解的支持,但是若既实现Ordered接口,又有@Order注解时,则优先从接口实现中获取值。实现原理主要还是覆写了OrderComparator#findOrder,增加了从注解中获取order的方法。
    • Ordered:排序接口,内有getOrder,用于给实现类返回自己的order;
    • PriorityOrdered:继承自Ordered,但是没有扩展任何方法,可以被视为一个标记。
    • Order:即@Order,是spring的注解,其value就是配置的order。
    • javax.annotation.Priority:即@Priority,javax的规范注解,其value就是配置的order

    排序数字:比较规则-越小的数字优先级越高,越大的数字优先级越低。

    3)AnnotationAwareOrderComparator源码解析

    order接口

    1. public interface Ordered {
    2. // 最高的优先级,实际数值为Integer的最小值
    3. int HIGHEST_PRECEDENCE = -2147483648;
    4. // 最低的优先级,实际数值为Integer的最大值
    5. int LOWEST_PRECEDENCE = 2147483647;
    6. int getOrder();
    7. }

    AnnotationAwareOrderComparator继承自OrderComparator,而OrderComparator则直接实现了Comparator,所以入口就在OrderComparator#compare中。

    1. public int compare(@Nullable Object o1, @Nullable Object o2) {
    2. // 调用内部的私有方法doCompare
    3. return this.doCompare(o1, o2, (OrderComparator.OrderSourceProvider)null);
    4. }
    5. private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderComparator.OrderSourceProvider sourceProvider) {
    6. // 优先PriorityOrdered
    7. boolean p1 = (o1 instanceof PriorityOrdered);
    8. boolean p2 = (o2 instanceof PriorityOrdered);
    9. // p1实现了PriorityOrdered,但是p2没实现PriorityOrdered,则p1优先级更高
    10. if (p1 && !p2) {
    11. return -1;
    12. }
    13. // p1没实现了PriorityOrdered,但是p2实现了PriorityOrdered,则p2优先级更高
    14. else if (p2 && !p1) {
    15. return 1;
    16. }
    17. // 方法执行到此,说明两者要么都实现了PriorityOrdered,或者都没实现PriorityOrdered,
    18. //则此时不再比较PriorityOrdered,开始比较order值
    19. // 调用内部私有方法getOrder
    20. int i1 = getOrder(o1, sourceProvider);
    21. int i2 = getOrder(o2, sourceProvider);
    22. return Integer.compare(i1, i2);
    23. }
    1. private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
    2. Integer order = null;
    3. // 由于doCompare方法传入的第二个参数OrderSourceProvider为空,所以这里的逻辑不会执行
    4. if (obj != null && sourceProvider != null) {
    5. Object orderSource = sourceProvider.getOrderSource(obj);
    6. if (orderSource != null) {
    7. if (orderSource.getClass().isArray()) {
    8. Object[] sources = ObjectUtils.toObjectArray(orderSource);
    9. for (Object source : sources) {
    10. order = findOrder(source);
    11. if (order != null) {
    12. break;
    13. }
    14. }
    15. }
    16. else {
    17. order = findOrder(orderSource);
    18. }
    19. }
    20. }
    21. // 直接执行这里的,调用getOrder继续获取order
    22. return (order != null ? order : getOrder(obj));
    23. }
    1. protected int getOrder(@Nullable Object obj) {
    2. if (obj != null) {
    3. // 调用findOrder从对象中获取order,该方法在AnnotationAwareOrderComparator中被覆写了
    4. Integer order = findOrder(obj);
    5. if (order != null) {
    6. return order;
    7. }
    8. }
    9. // 获取不到,则说明对象类没有实现Ordered,且没有@Order注解,默认最低优先级
    10. return Ordered.LOWEST_PRECEDENCE;
    11. }

    findOrder方法是定义在OrderComparator中的,但是子类AnnotationAwareOrderComparator又进行了覆写。

    先看看父类OrderComparator#findOrder方法

    1. protected Integer findOrder(Object obj) {
    2. // 可以看出仅仅只是从实现Ordered接口入手,获取其getOrder的值
    3. return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
    4. }

    再看看子类覆写的AnnotationAwareOrderComparator#findOrder

    1. protected Integer findOrder(Object obj) {
    2. // 优先调用父类OrderComparator#findOrder,即从Ordered接口入手,获取其getOrder的值
    3. Integer order = super.findOrder(obj);
    4. if (order != null) {
    5. return order;
    6. }
    7. // 获取不到时,再调用内部私有方法findOrderFromAnnotation从注解获取order
    8. return findOrderFromAnnotation(obj);
    9. }
    1. private Integer findOrderFromAnnotation(Object obj) {
    2. AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
    3. MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
    4. // 从@Order注解中获取order值,该方法会将class作为缓存key放入缓存map中,即同一个类第二次无需再读取注解的值
    5. Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
    6. if (order == null && obj instanceof DecoratingProxy) {
    7. return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
    8. }
    9. return order;
    10. }

    可以看出,内部是通过工具类OrderUtils获取排序注解的值

    1. static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) {
    2. // 由findOrderFromAnnotation可知,传入的必然是class对象
    3. if (!(element instanceof Class)) {
    4. return findOrder(annotations);
    5. }
    6. // 从缓存中以AnnotatedElement(此处为class)作为缓存key,获取order
    7. Object cached = orderCache.get(element);
    8. if (cached != null) {
    9. // 缓存不为空,直接返回order
    10. return (cached instanceof Integer ? (Integer) cached : null);
    11. }
    12. // 缓存为空,调用内部私有方法findOrder继续获取order
    13. Integer result = findOrder(annotations);
    14. // 将得到的order以key-AnnotatedElement,value-order放入缓存map中,
    15. //若result即order为空,则放入NOT_ANNOTATED(其实就是一个new Object())作为获取失败的
    16. orderCache.put(element, result != null ? result : NOT_ANNOTATED);
    17. return result;
    18. }
    1. private static Integer findOrder(MergedAnnotations annotations) {
    2. // 优先从@Order注解中获取order,获取成功直接返回其value
    3. MergedAnnotation orderAnnotation = annotations.get(Order.class);
    4. if (orderAnnotation.isPresent()) {
    5. return orderAnnotation.getInt(MergedAnnotation.VALUE);
    6. }
    7. // 用于获取@Priority注解的value(即javax.annotation.Priority)
    8. MergedAnnotation priorityAnnotation = annotations.get(JAVAX_PRIORITY_ANNOTATION);
    9. if (priorityAnnotation.isPresent()) {
    10. return priorityAnnotation.getInt(MergedAnnotation.VALUE);
    11. }
    12. return null;
    13. }

    总结:

    1、实现PriorityOrdered优先级更高,都有PriorityOrdered则比较各自的order(PriorityOrdered其实只是一个标记,虽然它继承自Ordered,但是没有扩展任何方法)
    2、都没有PriorityOrdered,则比较Ordered#getOrder、@Order#value以及javax.annotation.Priority,值小的优先级更高
    (此时,优先获取接口的Ordered#getOrder,若有则不再获取注解的@Order#value,若没有再获取注解@Order#value的值,若依然没有则尝试获取javax.annotation.Priority的值,都没有则默认返回最低优先级Ordered.LOWEST_PRECEDENCE)

    参考文章:详解Spring的核心排序类-AnnotationAwareOrderComparator

    二、Bean 后处理器

    1、代码测试 Bean 后处理器作用

    使用GenericApplicationContext原因:GenericApplicationContext 是一个【干净】的容器,【干净】指没有添加beanFactory处理器,bean处理器。

    DefaultListableBeanFactory也可以,但是使用起来比较麻烦。

    1. public class A04Application {
    2. public static void main(String[] args) {
    3. GenericApplicationContext context = new GenericApplicationContext();
    4. //用原始方法注册四个 bean
    5. context.registerBean("bean1", Bean1.class);
    6. context.registerBean("bean2", Bean2.class);
    7. context.registerBean("bean3", Bean3.class);
    8. context.registerBean("bean4", Bean4.class);
    9. //ContextAnnotationAutowireCandidateResolver 负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等
    10. context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
    11. context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
    12. // 初始化容器
    13. context.refresh(); // 执行beanFactory后处理器, 添加bean后处理器, 初始化所有单例
    14. System.out.println(context.getBean(Bean4.class));
    15. // 销毁容器
    16. context.close();
    17. }
    18. }
    1. public class Bean1 {
    2. private static final Logger log = LoggerFactory.getLogger(Bean1.class);
    3. private Bean2 bean2;
    4. @Autowired
    5. public void setBean2(Bean2 bean2) {
    6. log.debug("@Autowired 生效: {}", bean2);
    7. this.bean2 = bean2;
    8. }
    9. private Bean3 bean3;
    10. @Resource
    11. public void setBean3(Bean3 bean3) {
    12. log.debug("@Resource 生效: {}", bean3);
    13. this.bean3 = bean3;
    14. }
    15. private String home;
    16. @Autowired
    17. //没有写到属性上是方便打印一些信息
    18. public void setHome(@Value("${JAVA_HOME}") String home) {
    19. log.debug("@Value 生效: {}", home);
    20. this.home = home;
    21. }
    22. @PostConstruct
    23. public void init() {
    24. log.debug("@PostConstruct 生效");
    25. }
    26. @PreDestroy
    27. public void destroy() {
    28. log.debug("@PreDestroy 生效");
    29. }
    30. @Override
    31. public String toString() {
    32. return "Bean1{" +
    33. "bean2=" + bean2 +
    34. ", bean3=" + bean3 +
    35. ", home='" + home + '\'' +
    36. '}';
    37. }
    38. }
    1. public class Bean2 {
    2. }
    1. public class Bean3 {
    2. }
    1. @ConfigurationProperties(prefix = "java")
    2. public class Bean4 {
    3. private String home;
    4. private String version;
    5. public String getHome() {
    6. return home;
    7. }
    8. public void setHome(String home) {
    9. this.home = home;
    10. }
    11. public String getVersion() {
    12. return version;
    13. }
    14. public void setVersion(String version) {
    15. this.version = version;
    16. }
    17. @Override
    18. public String toString() {
    19. return "Bean4{" +
    20. "home='" + home + '\'' +
    21. ", version='" + version + '\'' +
    22. '}';
    23. }
    24. }

     结果:@Resource,@PostConstruct,@PreDestroy注解没有被解析

    1. com.itheima.a04.Bean1 - @Value 生效: D:\developer_tools\jdk\1.8.0_131
    2. com.itheima.a04.Bean1 - @Autowired 生效: com.itheima.a04.Bean2@21507a04
    3. Bean4{home='null', version='null'}

    1)添加CommonAnnotationBeanPostProcessor ,解析 @Resource、@PostConstruct、@PreDestroy

    context.registerBean(CommonAnnotationBeanPostProcessor.class);

    结果:发现先解析@Resource,后解析@Autowired,前面讲过,与后处理器顺序有关

    1. com.itheima.a04.Bean1 - @Resource 生效: com.itheima.a04.Bean3@1f1c7bf6
    2. com.itheima.a04.Bean1 - @Autowired 生效: com.itheima.a04.Bean2@691a7f8f
    3. com.itheima.a04.Bean1 - @Value 生效: D:\developer_tools\jdk\1.8.0_131
    4. com.itheima.a04.Bean1 - @PostConstruct 生效
    5. Bean4{home='null', version='null'}
    6. com.itheima.a04.Bean1 - @PreDestroy 生效

    2)添加ConfigurationPropertiesBindingPostProcessor ,解析 @ConfigurationProperties

    ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());

    结果:Bean4的依赖被注入

    1. com.itheima.a04.Bean1 - @Resource 生效: com.itheima.a04.Bean3@1f1c7bf6
    2. com.itheima.a04.Bean1 - @Autowired 生效: com.itheima.a04.Bean2@691a7f8f
    3. com.itheima.a04.Bean1 - @Value 生效: D:\developer_tools\jdk\1.8.0_131
    4. com.itheima.a04.Bean1 - @PostConstruct 生效
    5. Bean4{home='D:\developer_tools\jdk\1.8.0_131\jre', version='1.8.0_131'}
    6. com.itheima.a04.Bean1 - @PreDestroy 生效

    总结:

    • @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能,这些扩展功能由 bean 后处理器来完成
    • 每个后处理器各自增强什么功能

      • AutowiredAnnotationBeanPostProcessor 解析 @Autowired 与 @Value

      • CommonAnnotationBeanPostProcessor 解析 @Resource、@PostConstruct、@PreDestroy

      • ConfigurationPropertiesBindingPostProcessor 解析 @ConfigurationProperties

    • 另外 ContextAnnotationAutowireCandidateResolver 负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等

    2、@Autowired bean 后处理器运行分析

    AutowiredAnnotationBeanPostProcessor 运行分析

    1. public class DigInAutowired {
    2. public static void main(String[] args) throws Throwable {
    3. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    4. //注册单例
    5. beanFactory.registerSingleton("bean2", new Bean2());
    6. beanFactory.registerSingleton("bean3", new Bean3());
    7. beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
    8. beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${}的解析器
    9. AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
    10. processor.setBeanFactory(beanFactory);
    11. Bean1 bean1 = new Bean1();
    12. System.out.println(bean1);
    13. // 执行依赖注入 @Autowired
    14. processor.postProcessProperties(null, bean1, "bean1");
    15. System.out.println(bean1);
    16. }
    17. }

    结果:执行了postProcessProperties方法后依赖被注入

    1. Bean1{bean2=null, bean3=null, home='null'}
    2. com.itheima.a04.Bean1 - @Value 生效: D:\developer_tools\jdk\1.8.0_131
    3. com.itheima.a04.Bean1 - @Autowired 生效: com.itheima.a04.Bean2@2473b9ce
    4. Bean1{bean2=com.itheima.a04.Bean2@2473b9ce, bean3=null, home='D:\developer_tools\jdk\1.8.0_131'}

    postProcessProperties方法: 

    1. /*
    2. 参数一:指定bean的每个属性的值,由于不需要,为null
    3. 参数二:被注入的目标
    4. 参数三:被注入的名字
    5. */
    6. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    7. InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);
    8. try {
    9. //用反射给属性赋值
    10. metadata.inject(bean, beanName, pvs);
    11. return pvs;
    12. } catch (BeanCreationException var6) {
    13. throw var6;
    14. } catch (Throwable var7) {
    15. throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
    16. }
    17. }

    下面对这个方法的步骤进行分解

    步骤一:查找哪些属性、方法加了 @Autowired,结果封装成 InjectionMetadata

    反射调用findAutowiringMetadata方法

    1. public class DigInAutowired {
    2. public static void main(String[] args) throws Throwable {
    3. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    4. //注册单例
    5. beanFactory.registerSingleton("bean2", new Bean2());
    6. beanFactory.registerSingleton("bean3", new Bean3());
    7. beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
    8. beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${}的解析器
    9. AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
    10. processor.setBeanFactory(beanFactory);
    11. Bean1 bean1 = new Bean1();
    12. Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.
    13. getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
    14. findAutowiringMetadata.setAccessible(true);
    15. // 获取 Bean1 上加了 @Value @Autowired 的成员变量,方法参数信息
    16. InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
    17. System.out.println(metadata);
    18. }
    19. }

    debug查看metadata

    如果我在Bean1类添加

    1. @Autowired
    2. private String aaa;

     结果:size变为3了

     步骤二:调用 InjectionMetadata 来进行依赖注入, 注入时按类型查找值

    1. metadata.inject(bean1, "bean1", null);
    2. System.out.println(bean1);

    结果:

    Bean1{bean2=com.itheima.a04.Bean2@3d0f8e03, bean3=null, home='D:\developer_tools\jdk\1.8.0_131'}

     如何按类型查找值

    1. Field bean3 = Bean1.class.getDeclaredField("bean3");
    2. //spring内部将其封装成 DependencyDescriptor 对象
    3. //参数一:成员变量 参数二:是否必须
    4. DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
    5. //根据成员变量的信息得到它的类型,进而根据类型找到容器中符合的bean
    6. Object o = beanFactory.doResolveDependency(dd1, null, null, null);
    7. System.out.println(o);
    8. //最后根据反射调用set方法给bean1
    9. //@Autowire在方法上
    10. Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
    11. //spring内部将其封装成 DependencyDescriptor 对象
    12. //MethodParameter 参数一:方法 参数二:方法的第几个参数
    13. DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);
    14. Object o2 = beanFactory.doResolveDependency(dd2, null, null, null);
    15. System.out.println(o2);
    16. Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
    17. DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome, 0), true);
    18. Object o3 = beanFactory.doResolveDependency(dd3, null, null, null);
    19. System.out.println(o3);

    结果:

    1. com.itheima.a04.Bean3@5fbdfdcf
    2. com.itheima.a04.Bean2@2df9b86
    3. D:\developer_tools\jdk\1.8.0_131

    总结:

    1. AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为 InjectionMetadata

    2. InjectionMetadata 可以完成依赖注入

    3. InjectionMetadata 内部根据成员变量,方法参数封装为 DependencyDescriptor 类型

    4. 有了 DependencyDescriptor,就可以利用 beanFactory.doResolveDependency 方法进行基于类型的查找

  • 相关阅读:
    CSS选择器分类( 通配符、标签选择器、id选择器、类选择器)
    GBase 8s是否支持自动实时跟踪、监控和调优
    SuperMap iServer 产品包类型说明
    深入解析Java正则表达式:定义、原理和实例
    TSINGSEE青犀智能分析网关工服识别算法,如何最大限度保障工人安全?
    【Linux】C文件系统详解(一)——C文件操作
    供给需求双轮驱动安全应急产业高质量发展
    IP地址在网络安全中的关键作用
    【 数据分析概述与职业操守】——CDA level1
    LaTeX学习笔记
  • 原文地址:https://blog.csdn.net/qq_51409098/article/details/127645677