java中spring技巧之扩展点的应用-mile米乐体育
目录
- 前言:
- 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 beansexception { defaultlistablebeanfactory fac = (defaultlistablebeanfactory) beanfactory; map
「instantiationawarebeanpostprocessor#postprocesspropertyvalues」
非常规的配置项比如
<http://www.cppcns.com;context:component-scan base-package="com.zhou" />
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 postprocesspropertyva恰卡编程网lues(propertyvalues pvs, propertydescriptor[] pds, object bean, string beanname) throws beansexception { 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 pvs; } }
我们看到在postprocesspropertyvalues
方法中,进行了属性注入
「invokeaware」
实现beanfactoryaware接口的类,会由容器执行setbeanfactory方法将当前的容器beanfactory注入到类中
@bean class beanfactoryholder implements beanfactoryaware{ private static beanfactory beanfactory; public void setbeanfactory(beanfactory beanfactory) throws beansexception { this.beanfactory = beanfactory; } }
「beanpostprocessor#postprocessbeforeinitialization」
实现applicationcontextaware接口的类,会由容器执行setapplicationcontext方法将当前的容器applicationcontext注入到类中
@bean class applicationcontextawareprocessor implements http://www.cppcns.combeanpostprocessor { private final configurableapplicationcontext applicationcontext; public applicationcontextawareprocessor(configurableapplicationcontext applicationcontext) { this.applicationcontext = applicationcontext; } @override public object postprocessbeforeinitialization(final object bean, string beanname) throws beansexception { //... 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 beansexception { this.applicationcontext = applicationcontext; } }
「afterpropertyset()和init-method」
目前很多java中间件都是基本spring framework搭建的,而这些中间件经常把入口放到afterpropertyset或者自定义的init中
「beanpostprocessor#postprocessafterinitialization」
熟悉aop的同学应该知道,aop底层是通过动态代理实现的
当配置了
时候,默认开启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 beansexception { if (bean != null) { object cachekey = getcachekey(bean.getclass(), beanname); if (!this.earlyproxyreferences.containskey(cachekey)) { //如果该类需要被代理,返回动态代理对象;反之,返回原对象 return wrapifnecessary(bean, beanname, cachekey); } } return bean; } }
正是利用spring的这个扩展点实现了动态代理对象的替换
「destroy()和destroy-method」
bean生命周期的最后一个扩展点,该方法用于执行一些bean销毁前的准备工作,比如将当前bean持有的一些资源释放掉
总结
到此这篇关于java中spring技巧之扩展点的应用的文章就介绍到这了,更多相关spring扩展点应用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!