2023-09-16  阅读(30)
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105173363

图不能少

202309162313357281.png

applyMergedBeanDefinitionPostProcessors

在实例化之后,合并bean定义,其实就是更新bean定义啦,这里可以再次修改bean定义,这里只能修改RootBeanDefinition类型的。前面说过了,主要还是InitDestroyAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor处理有注入注解的属性或者方法。分别去处理生命周期PostConstructPreDestroy注解,Resource,WebServiceRef,EJB注解AutowiredValue注解。

applyBeanPostProcessorsAfterInitialization

其实这个可以和上面那个配合,比如上面那个做一些处理,这个后面就可以用,我们下面来做简单的子类看看。

202309162313365062.png

扩展点实战

我想定义一个注解,注解上有个属性,就是要打印方法的次数,我希望能找到所有这个属性定义的方法,然后打印他们。

MyAnnotation注解

属性count就是打印的次数。

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
        int count() default 0;
    }

MyMergedBean

我们注解一些方法, 看看他会不会打印。

    @Component
    public class MyMergedBean {
    
        @MyAnnotation(count = 1)
        public void m1(String msg) {
            print(msg);
        }
    
        @MyAnnotation(count = 2)
        public void m2(String msg) {
            print(msg);
        }
    
        @MyAnnotation()
        public void m3(String msg) {
            print(msg);
        }
    
        private void print(String msg) {
            System.out.println(msg);
        }
    }

MyMergedBeanDefinitionPostProcessor 处理器

这里主要是实现了postProcessMergedBeanDefinition,做了实例化之后的处理,然后在初始化后postProcessBeforeInitialization具体进行处理。主要是打印有注解的方法,根据注解的属性。

    @Component
    public class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
    
        //bean名字对应的注解方法
        public Map<String,List<Method>> stringMethodMap;
    
        @Nullable
        private Class<? extends Annotation> myAnnotationType;
    
        public MyMergedBeanDefinitionPostProcessor(){
            myAnnotationType=MyAnnotation.class;
            stringMethodMap=new HashMap<>();
    
        }
    
        @Override
        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
            List<Method> list=new ArrayList<>();
            ReflectionUtils.doWithLocalMethods(beanType, method -> {
                if (this.myAnnotationType != null && method.isAnnotationPresent(this.myAnnotationType)) {
                    list.add(method);
                    stringMethodMap.put(beanName,list);
                }
            });
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if(stringMethodMap.get(beanName)!=null){
                for (Method method : stringMethodMap.get(beanName)) {
                    try {
                        MyAnnotation annotation = (MyAnnotation) method.getAnnotation(this.myAnnotationType);
                        for (int i = 0; i < annotation.count(); i++) {
                            method.invoke(bean,new Object[]{method.getName()});
                        }
    
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            return bean;
        }
    }

测试类

       @Test
        public void MergedBeanDefinitionPostProcessorTest() throws Exception {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            applicationContext.register(MyConfig.class);
            applicationContext.refresh();
    
        }

202309162313369803.png
我再改改:

202309162313375004.png
结果:

202309162313379075.png
为什么不是按定义顺序执行呢,好像是因为JDK反射拿出来就是无序的,如果要有序可以用CGLIBClassVisitor来拿,具体spring源码里有,可以参考ConfigurationClassParserretrieveBeanMethodMetadata

202309162313386776.png

好了,MyMergedBeanDefinitionPostProcessor到底有什么用呢,就看你的业务啦,只要你想在实例化后做扩展,就可以尝试用这个,参与bean的初始化的过程。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文