热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring5.x源码之旅三十七之MergedBeanDefinitionPostProcessor扩展点

Spring5.x源码之旅三十七之MergedBeanDefinitionPostProcessor扩展点图不能少applyMergedBeanDefinitionPostProc

Spring 5.x 源码之旅三十七之MergedBeanDefinitionPostProcessor扩展点

  • 图不能少
  • applyMergedBeanDefinitionPostProcessors
  • applyBeanPostProcessorsAfterInitialization
  • 扩展点实战
    • MyAnnotation注解
    • MyMergedBean
    • MyMergedBeanDefinitionPostProcessor 处理器
    • 测试类


图不能少

在这里插入图片描述

applyMergedBeanDefinitionPostProcessors

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

applyBeanPostProcessorsAfterInitialization

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

扩展点实战

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

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;&#64;Nullableprivate Class<? extends Annotation> myAnnotationType;public MyMergedBeanDefinitionPostProcessor(){myAnnotationType&#61;MyAnnotation.class;stringMethodMap&#61;new HashMap<>();}&#64;Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {List<Method> list&#61;new ArrayList<>();ReflectionUtils.doWithLocalMethods(beanType, method -> {if (this.myAnnotationType !&#61; null && method.isAnnotationPresent(this.myAnnotationType)) {list.add(method);stringMethodMap.put(beanName,list);}});}&#64;Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if(stringMethodMap.get(beanName)!&#61;null){for (Method method : stringMethodMap.get(beanName)) {try {MyAnnotation annotation &#61; (MyAnnotation) method.getAnnotation(this.myAnnotationType);for (int i &#61; 0; i < annotation.count(); i&#43;&#43;) {method.invoke(bean,new Object[]{method.getName()});}} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}return bean;}
}

测试类

&#64;Testpublic void MergedBeanDefinitionPostProcessorTest() throws Exception {AnnotationConfigApplicationContext applicationContext &#61; new AnnotationConfigApplicationContext();applicationContext.register(MyConfig.class);applicationContext.refresh();}

在这里插入图片描述
我再改改&#xff1a;
在这里插入图片描述
结果&#xff1a;
在这里插入图片描述
为什么不是按定义顺序执行呢&#xff0c;好像是因为JDK反射拿出来就是无序的&#xff0c;如果要有序可以用CGLIBClassVisitor来拿&#xff0c;具体spring源码里有&#xff0c;可以参考ConfigurationClassParserretrieveBeanMethodMetadata&#xff1a;
在这里插入图片描述

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

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


推荐阅读
author-avatar
firespace
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有