当前位置: 首页 > 科技观察

Spring奇技巧匠之扩展点的应用

时间:2023-03-19 10:08:21 科技观察

本文转载自微信公众号《月亮与飞鱼》,作者日常加油站。转载本文请联系月版飞鱼公众号.最近在看公司的项目和中间件的时候,看到了一些Spring扩展点的使用。写了一篇文章学习,对大家后面看源码有帮助。“首先介绍一下Bean的生命周期。”我们知道Bean的生命周期Bean(单例非懒加载)实例化阶段Bean属性注入阶段Bean初始化阶段Bean销毁阶段下面是整个Spring容器的启动过程。可以看到,除了上面的几个主干流程,Spring还提供了很多扩展点。下面详细介绍Spring的常用扩展点。项目的xml执行单机测试耗时较长(大部分时间花在了xml中数百个单例非懒加载bean的实例化和初始化过程)。将bean设置为延迟加载模式,省去了Bean的实例化与初始化时间publicclassLazyBeanFactoryProcessorimplementsBeanFactoryPostProcessor{@OverridepublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory)throwsBeansException{DefaultListableBeanFactoryfac=(DefaultListableBeanFactory)beanFactory;Mapmap=(Map)ReflectionTestUtils.getField(fac,"beanDefinitionMap");for(Map.Entryentry:map.entrySet()){//设置为延迟加载entry.getValue().setLazyInit(true);}}}"实例化nAwareBeanPostProcessor#postProcessPropertyValues》等非常规配置项Spring提供了与之对应的特殊解析器,正是通过这些特殊的解析器,相应的配置项才能生效的解析器对于这个特殊的配置是ComponentScanBeanDefinitionParser,在这个parser的解析方法中,注册了很多特殊的BeanpublicBeanDefinitionparse(Elementelement,ParserContextparserContext){//...registerComponents(parserContext.getReaderContext(),beanDefinitions,element);//...returnnull;}publicstaticSetregisterAnnotationConfigProcessors(BeanDefinitionRegistryregistry,Objectsource){SetbeanDefs=newLinkedHashSet(4);//...//@Autowireif(!registry.containsBeanDefinition(AUTOTIONBEANRED_PRONORED_ANNOORTA)){RootdefinitionBeanDefinition(AUTOTIONBEANRED_PRONORED_ANNOORTA))AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry,def,AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}//检查是否支持JSR-250,如果存在addtheCommonAnnotationBeanPostProcessor.//@Resourceif(jsr250Present&&!registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)){//特殊的BeanRootBeanDefinitiondef=newRootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry,def,COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}//...returnbeanDefs;}以@Resource为例,看看这个特殊的bean做了什么publicclassCommonAnnotationBeanPostProcessorextendsInitDestroyAnnotationBeanPostProcessorimplementsInstantiationAwareBeanPostProcessor,BeanFactoryAware,Serializable{publicPropertyValuespostProcessPropertyValues(PropertyValuespvs,PropertyDescriptor[]pds,Objectbean,StringbeanName)throwsBeansException{InjectionMetadatametadata=findResourceMetadata(beanName,bean.getClass());try{//属性注入metadata.inject(bean,beanName,pvs);}catch(Throwableex){thrownewBeanCreationException(beanName,"Injectionofresourcedependenciesfailed",ex);}returnpvs;}}我们看到了postProcessPro在pertyValues方法中,属性注入“invokeAware”实现了BeanFactoryAware接口的类,容器执行setBeanFactory方法将当前容器BeanFactory注入到类中}「BeanPostProcessor#postProcessBeforeInitialization」实现ApplicationContextAware接口的类,会由容器执行setApplicationContext方法将当前的容器applicationContext注入到类中@BeanclassApplicationContextAwareProcessorimplementsBeanPostProcessor{privatefinalConfigurableApplicationContextapplicationContext;publicApplicationContextAwareProcessor(ConfigurableApplicationContextapplicationContext){this.applicationContext=applicationContext;}@OverridepublicObjectpostProcessBeforeInitialization(finalObjectbean,StringbeanName)throwsBeansException{//...invokeAwareInterfaces(bean);returnbean;}privatevoidinvokeAwareInterfaces(Objectbean){if(beaninstanceofApplicationContextAware){((ApplicationContextAware)是an).setApplicationContext(this.applicationContext);}}}我们看到是在BeanPostProcessor的postProcessBeforeInitialization中进行了setApplicationContext方法的调用classApplicationContextHolderimplementsApplicationContextAware{privatestaticApplicationContextapplicationContext;publicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeanstyException{this.applicationContextSet=after}和init-method”目前很多Java中间件都是用SpringFramework基础构建的,而这些中间件往往把入口放在afterPropertySet或者自定义init“BeanPostProcessor#postProcessAfterInitialization”熟悉aop的同学应该都知道aop的底层在通过配置动态代理的时候,默认开启了aop功能,相应的,调用者需要被aop织入的对象也需要换成动态代理对象,不知道大家有没有想过动态代理是如何“不知道来电者。根据上面的解释,我们知道:Spring也提供了一个特殊的解析器,和其他解析器类似,注册在核心解析方法中这里的bean是一个BeanPostProcessor类型的beanclassAspectJAutoProxyBeanDefinitionParserimplementsBeanDefinitionParser{@OverridepublicBeanDefinitionparse(Elementelement,ParserContextparserContext){//注册特殊beanAopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext,element);extendBeanDefinition(element,parserContext);returnnull;}}将于当前bean对应的动态代理对象返回即可,该过程对调用方全部透明publicclassAnnotationAwareAspectJAutoProxyCreatorextendsAspectJAwareAdvisorAutoProxyCreator{publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{if(bean!=null){ObjectcacheKey=getCacheKey(bean.getClass(),beanName);if(!this.earlyProxyReferences.containsKey(cacheKey)){//如果类需要被代理,则返回动态代理对象;否则返回原来的对象returnwrapIfNecessary(bean,beanName,cacheKey);}}returnbean;}}就是利用Spring的这个扩展点来实现动态代理对象“destroy()和destroy-method”的替换。该方法用于进行bean销毁前的一些准备工作,比如释放当前bean持有的一些资源

最新推荐
猜你喜欢