怎样在小程序里实现标题的更改
652
2022-09-26
Spring奇技淫巧之扩展点的应用!
前言
觉得有收获,希望帮忙点赞,转发下哈,谢谢,谢谢
最近在看公司项目和中间件的时候,看到一些Spring扩展点的使用,写篇文章学习下,对大家之后看源码都有帮助
「首先先介绍下Bean的生命周期」
我们知道Bean的生命周期分为几个主干流程
Bean(单例非懒加载)的实例化阶段Bean的属性注入阶段Bean的初始化阶段Bean的销毁阶段
下面是整个Spring容器的启动流程,可以看到除了上述几个主干流程外,Spring还提供了很多扩展点
下面详细介绍下Spring的常见的扩展点
Spring常见扩展点
「BeanFactoryPostProcessor#postProcessBeanFactory」
有时候整个项目工程中bean的数量有上百个,而大部分单测依赖都是整个工程的xml,导致单测执行时需要很长时间(大部分时间耗费在xml中数百个单例非懒加载的bean的实例化及初始化过程)
解决方法:利用Spring提供的扩展点将xml中的bean设置为懒加载模式,省去了Bean的实例化与初始化时间
public class LazyBeanFactoryProcessor implements BeanFactoryPostProcessor{ @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws{ DefaultListableBeanFactory fac = (DefaultListableBeanFactory) beanFactory; Map
「InstantiationAwareBeanPostProcessor#postProcessPropertyValues」
非常规的配置项比如
Spring提供了与之对应的特殊解析器 正是通过这些特殊的解析器才使得对应的配置项能够生效 而针对这个特殊配置的解析器为 ComponentScanBeanDefinitionParser 在这个解析器的解析方法中,注册了很多特殊的Bean public BeanDefinition parse(Element element, ParserContext parserContext){ //... registerComponents(parserContext.getReaderContext(), beanDefinitions, element); //... return null;}public static Set 以@Resource为例,看看这个特殊的bean做了什么 public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable{ public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws{ InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass()); try { //属性注入 metadata.inject(bean, beanName, pvs); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex); } return 我们看到在postProcessPropertyValues方法中,进行了属性注入 「invokeAware」 实现BeanFactoryAware接口的类,会由容器执行setBeanFactory方法将当前的容器BeanFactory注入到类中 @Beanclass BeanFactoryHolder implements BeanFactoryAware{ private static BeanFactory beanFactory; public void setBeanFactory(BeanFactory beanFactory) throws{ this.beanFactory = beanFactory; }} 「BeanPostProcessor#postProcessBeforeInitialization」 实现ApplicationContextAware接口的类,会由容器执行setApplicationContext方法将当前的容器applicationContext注入到类中 @Beanclass ApplicationContextAwareProcessor implements BeanPostProcessor{ private final ConfigurableApplicationContext applicationContext; public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext){ this.applicationContext = applicationContext; } @Override public Object postProcessBeforeInitialization(final throws{ //... invokeAwareInterfaces(bean); return bean; } private void invokeAwareInterfaces(Object bean){ if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } }} 我们看到是在BeanPostProcessor的postProcessBeforeInitialization中进行了setApplicationContext方法的调用 class ApplicationContextHolder implements ApplicationContextAware{ private static ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) throws{ this.applicationContext = applicationContext; }} 「afterPropertySet()和init-method」 目前很多Java中间件都是基本Spring Framework搭建的,而这些中间件经常把入口放到afterPropertySet或者自定义的init中 「BeanPostProcessor#postProcessAfterInitialization」 熟悉aop的同学应该知道,aop底层是通过动态代理实现的 当配置了 不知道大家有没有思考过动态代理是如何**「在调用方无感知情况下替换原始对象」**的? ❝根据上文的讲解,我们知道:❞ Spring也提供了特殊的解析器,和其他的解析器类似,在核心的parse方法中注册了特殊的bean 这里是一个BeanPostProcessor类型的bean class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser{ @Override public BeanDefinition parse(Element element, ParserContext parserContext){ //注册特殊的bean AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); extendBeanDefinition(element, parserContext); return null; }} 将于当前bean对应的动态代理对象返回即可,该过程对调用方全部透明 public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator{ public Object postProcessAfterInitialization(Object bean, String beanName) throws{ if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.containsKey(cacheKey)) { //如果该类需要被代理,返回动态代理对象;反之,返回原对象 return wrapIfNecessary(bean, beanName, cacheKey); } } return 正是利用Spring的这个扩展点实现了动态代理对象的替换 「destroy()和destroy-method」 bean生命周期的最后一个扩展点,该方法用于执行一些bean销毁前的准备工作,比如将当前bean持有的一些资源释放掉 最后 「写文章画图不易,喜欢的话,希望帮忙点赞,转发下哈,谢谢」 参考书籍: Spring技术内幕Spring源码深度解析
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~