Spring学习10-- AOP实现原理
2017-01-05 22:40
483 查看
AOP的原理不需要多讲,动态代理。那么,Spring在bean对象实例化的时候,是如何动态代理一个类的呢?又是如何完成方法织入的呢,来看一看源码。
1、AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInstantiation
翻开Spring学习08的内容,里面有讲到后置处理器BeanPostProcessor的实现原理,在给Bean实例化的过程中,调用了该类中的ceaterBean方法,里面有处理后置处理器的入口函数的调用
以applyBeanPostProcessorsAfterInitialization为例子,进入该方法
真正处理的方法是postProcessAfterInitialization,继续进去看看,AbstractAutowireCapableBeanFactory类中并没有实现这个方法,查看一下子类,真正实现的地方在AbstractAutoProxyCreator
真正创建代理的地方入口就在这里,进入createProxy
正在返回代理的地方就是最后的getProxy()方法,进入,但是类中没有实现,在子类JdkDynamicAopProxy中有了实现
这样一个过程下来,一个代理对象就产生了,但是问题又来了,这个对象是如何工作的,也就是说,是如何织入的呢?
2、织入过程
上面说到类JdkDynamicAopProxy中geyProxy方法产生了一个代理对象,我们在动态代理中说过,动态代理最重要的地方就是实现InvocationHandler接口,其中invoke函数是代理生效的方法,正好,类JdkDynamicAopProxy就实现了这个接口,来找一下invoke方法,看里面做了写什么。
过程如下:
1、Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
2、获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint; 如果没有,则直接反射执行joinpoint
获取通知链的过程getInterceptorsAndDynamicInterceptionAdvice,进入查看一下。这个方法在子类中实现。
实际调用的是calculateInterceptorsAndDynamicInterceptionAdvice,进入查看
这个方法的作用就是
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
调用此方法获取目标对象方法配置的拦截器(通知器)链 。
返回上一层代码,查看一下拦截器链是怎么起作用的
JdkDynamicAopProxy 和CglibAopProxy创建AOPProxy代理对象,以及对目标对象的通知器回调我们了解到,当目标对象配置了通知器时,在对目标对象方法调用前首先需要回调通知器链,JdkDynamicAopProxy和CglibAopProxy都是通过将目标对象方法、方法参数、和通知器链、代理对象等封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链
proceed方法源码如下
总结一下
1、AOP创建代理对象通过ProxyFactory创建的。
2、JdkDynamicAopProxy通过JDK提供的动态代理创建代理类,实现方式有两种一种是jdk的动态代理,如果没有实现接口,则使用CGLIB字节码技术生成代理类。
3、代理类创建通过invoke方法调用,主要是获取目标对象方法、方法参数、和通知器链、代理对象等。
4、将上述获取到的目标对象数据封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链。
1、AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInstantiation
翻开Spring学习08的内容,里面有讲到后置处理器BeanPostProcessor的实现原理,在给Bean实例化的过程中,调用了该类中的ceaterBean方法,里面有处理后置处理器的入口函数的调用
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. if (beanClass != null && !mergedBeanDefinition.isSynthetic()) { //bean对象初始化之前的处理入口 Object bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName); if (bean != null) { //bean对象初始化之后的处理入口 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); return bean; } }
以applyBeanPostProcessorsAfterInitialization为例子,进入该方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; //遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { //调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在 //初始化之后做一些自定义的处理操作 result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }
真正处理的方法是postProcessAfterInitialization,继续进去看看,AbstractAutowireCapableBeanFactory类中并没有实现这个方法,查看一下子类,真正实现的地方在AbstractAutoProxyCreator
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (isInfrastructureClass(bean.getClass(), beanName) || shouldSkip(bean.getClass(), beanName)) { return bean; } // Create proxy if we have advice. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { //创建代理 return createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); } return bean; }
真正创建代理的地方入口就在这里,进入createProxy
protected Object createProxy( Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { // handle prototypes correctly //获取所有的advisor, Advisor:充当Advice和Pointcut的适配器,类似使用Aspect的@Aspect注解的类(前一章节所//述)。一般有advice和pointcut属性 Advisor[] commonInterceptors = resolveInterceptorNames(); List allInterceptors = new ArrayList(); if (specificInterceptors != null) { allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors != null) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } if (logger.isDebugEnabled()) { int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.length : 0; int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.length : 0; logger.debug( "Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors"); } ProxyFactory proxyFactory = new ProxyFactory(); // Copy our properties (proxyTargetClass) inherited from ProxyConfig. proxyFactory.copyFrom(this); if (!isProxyTargetClass()) { // Must allow for introductions; can't just set interfaces to // the target's interfaces only. Class[] targetsInterfaces = ClassUtils.getAllInterfacesForClass(beanClass); for (int i = 0; i < targetsInterfaces.length; i++) { proxyFactory.addInterface(targetsInterfaces[i]); } } for (Iterator it = allInterceptors.iterator(); it.hasNext();) { Advisor advisor = this.advisorAdapterRegistry.wrap(it.next()); proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); //返回代理对象 return proxyFactory.getProxy(); }
正在返回代理的地方就是最后的getProxy()方法,进入,但是类中没有实现,在子类JdkDynamicAopProxy中有了实现
/** * <ol> * <li>获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false) * <li>检查上面得到的接口中有没有定义 equals或者hashcode的接口 * <li>调用Proxy.newProxyInstance创建代理对象 * </ol> */ public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " +this.advised.getTargetSource()); } Class[] proxiedInterfaces =AopProxyUtils.completeProxiedInterfaces(this.advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
这样一个过程下来,一个代理对象就产生了,但是问题又来了,这个对象是如何工作的,也就是说,是如何织入的呢?
2、织入过程
上面说到类JdkDynamicAopProxy中geyProxy方法产生了一个代理对象,我们在动态代理中说过,动态代理最重要的地方就是实现InvocationHandler接口,其中invoke函数是代理生效的方法,正好,类JdkDynamicAopProxy就实现了这个接口,来找一下invoke方法,看里面做了写什么。
//AOP代理对象的回调方法 publicObject invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocationinvocation; ObjectoldProxy = null; booleansetProxyContext = false; //获取通知的目标源 TargetSourcetargetSource = this.advised.targetSource; ClasstargetClass = null; Objecttarget = null; try{ //如果代理目标对象的接口中没有定义equals()方法,且当前调用的方法 //是equals()方法,即目标对象没有自己实现equals()方法 if(!this.equalsDefined && AopUtils.isEqualsMethod(method)) { returnequals(args[0]); } //如果代理目标对象的接口中没有定义hashCode()方法,且当前调用的方法 //是hashCode()方法,即目标对象没有自己实现hashCode()方法 if(!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { returnhashCode(); } //如果AOP配置了通知,使用反射机制调用通知的同名方法 if(!this.advised.opaque && method.getDeclaringClass().isInterface()&& method.getDeclaringClass().isAssignableFrom(Advised.class)){ returnAopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } ObjectretVal; //如果当前通知暴露了代理,则将当前代理使用currentProxy()方法变为可用代理 if(this.advised.exposeProxy) { oldProxy= AopContext.setCurrentProxy(proxy); setProxyContext= true; } //获取目标对象 target= targetSource.getTarget(); if(target != null) { targetClass= target.getClass(); } //获取目标对象方法配置的拦截器(通知器)链 List<Object>chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass); //如果没有配置任何通知 if(chain.isEmpty()) { //没有配置通知,使用反射直接调用目标对象的方法,并获取方法返回值 retVal= AopUtils.invokeJoinpointUsingReflection(target, method, args); } //如果配置了通知 else{ //为目标对象创建方法回调对象,需要在调用通知之后才调用目标对象的方法 invocation= new ReflectiveMethodInvocation(proxy, target, method, args, targetClass,chain); //调用通知链,沿着通知器链调用所有配置的通知 retVal= invocation.proceed(); } //如果方法有返回值,则将代理对象最为方法返回 if(retVal != null && retVal == target &&method.getReturnType().isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())){ retVal= proxy; } returnretVal; } finally{ if(target != null && !targetSource.isStatic()) { //释放目标对象 targetSource.releaseTarget(target); } if(setProxyContext) { //存储代理对象 AopContext.setCurrentProxy(oldProxy); } } }
过程如下:
1、Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
2、获取可以应用到此方法上的通知链(Interceptor Chain),如果有,则应用通知,并执行joinpoint; 如果没有,则直接反射执行joinpoint
获取通知链的过程getInterceptorsAndDynamicInterceptionAdvice,进入查看一下。这个方法在子类中实现。
public List getInterceptorsAndDynamicInterceptionAdvice( Advised config, Object proxy, Method method, Class targetClass) { List cached = (List) this.methodCache.get(method); if (cached == null) { // recalculate cached = AdvisorChainFactoryUtils.calculateInterceptorsAndDynamicInterceptionAdvice( config, proxy, method, targetClass); this.methodCache.put(method, cached); } return cached; }
实际调用的是calculateInterceptorsAndDynamicInterceptionAdvice,进入查看
/** * Return the static interceptors and dynamic interception advice that may apply * to this method invocation. * @return list of MethodInterceptor and InterceptionAdvice (if there's a dynamic * method matcher that needs evaluation at runtime) */ public static List calculateInterceptorsAndDynamicInterceptionAdvice( Advised config, Object proxy, Method method, Class targetClass) { // this is somewhat tricky... we have to process introductions first, // but we need to preserve order in the ultimate list. List interceptorList = new ArrayList(config.getAdvisors().length); boolean hasIntroductions = hasMatchingIntroductions(config,targetClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); for (int i = 0; i < config.getAdvisors().length; i++) { Advisor advisor = config.getAdvisors()[i]; if (advisor instanceof PointcutAdvisor) { // add it conditionally PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (methodMatches(mm,method, targetClass,hasIntroductions)) { if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (int j = 0; j < interceptors.length; j++) { interceptorList.add(new InterceptorAndDynamicMethodMatcher((MethodInterceptor) interceptors[j], mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (ia.getClassFilter().matches(targetClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } } return interceptorList; }
这个方法的作用就是
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
调用此方法获取目标对象方法配置的拦截器(通知器)链 。
返回上一层代码,查看一下拦截器链是怎么起作用的
JdkDynamicAopProxy 和CglibAopProxy创建AOPProxy代理对象,以及对目标对象的通知器回调我们了解到,当目标对象配置了通知器时,在对目标对象方法调用前首先需要回调通知器链,JdkDynamicAopProxy和CglibAopProxy都是通过将目标对象方法、方法参数、和通知器链、代理对象等封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链
proceed方法源码如下
//通用通知器链 public Object proceed() throws Throwable { //如果拦截器链中通知已经调用完毕 if(this.currentInterceptorIndex ==this.interceptorsAndDynamicMethodMatchers.size() - 1) { //这个方法调用AopUtils.invokeJoinpointUsingReflection方法, //通过反射机制直接调用目标对象方法 returninvokeJoinpoint(); } //获取拦截器链中的通知器或通知 ObjectinterceptorOrInterceptionAdvice= this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //如果获取的通知器或通知是动态匹配方法拦截器类型 if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher){ //动态匹配方法拦截器 InterceptorAndDynamicMethodMatcherdm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice; if(dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { //如果匹配,调用拦截器的方法 returndm.interceptor.invoke(this); } else{ //如果不匹配,递归调用proceed()方法,知道拦截器链被全部调用为止 returnproceed(); } } else{ //如果不是动态匹配方法拦截器,则切入点在构造对象之前进行静态匹配,调用 //拦截器的方法 return((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
总结一下
1、AOP创建代理对象通过ProxyFactory创建的。
2、JdkDynamicAopProxy通过JDK提供的动态代理创建代理类,实现方式有两种一种是jdk的动态代理,如果没有实现接口,则使用CGLIB字节码技术生成代理类。
3、代理类创建通过invoke方法调用,主要是获取目标对象方法、方法参数、和通知器链、代理对象等。
4、将上述获取到的目标对象数据封装为ReflectiveMethodInvocation类,然后通过ReflectiveMethodInvocation.proceed()方法调用通知器链。
相关文章推荐
- spring源码学习之:springAOP实现底层原理
- java学习笔记10 - 以@AspectJ方式在Spring中实现AOP
- 【spring学习笔记三】aop思想介绍及实现原理
- Spring AOP学习(三) -- Spring AOP实现原理
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- spring AOP实现原理
- 反射实现AOP 动态代理模式(Spring AOP 的实现原理)
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理) --转
- ITCAST视频-Spring学习笔记(编码剖析@Resource注解的实现原理)
- ITCAST视频-Spring学习笔记(使用JDK中的Proxy技术实现AOP功能)
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- ITCAST视频-Spring学习笔记(使用Spring配置文件实现AOP)
- ITCAST视频-Spring学习笔记(使用Spring的注解方式实现AOP的细节)
- Spring视频学习(六)JDK和cglib实现AOP
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)