Spring源码阅读4.2-Aspecjt AOP之代理对象的创建
2015-12-11 14:55
856 查看
继续上一篇的话题,在《Spring源码阅读4.1-Aspecjt AOP之获取Adivsor》,我们说获取了所有的AspectJ以及其Advisor,其中每个Advisor都和其Aspectj类的表达式一起缓存到了数组中,以便后续直接使用。在这里要补充一下InstantiationModelAwarePointcutAdvisorImpl对象的初始化。只上源码:
在instantiateAdivice方法中,根据不同的类型创建了不同的Advice对象。
我们回到AspectJAwareAdvisorAutoProxyCreator的父类AbstractAdvisorAutoProxyCreator的findEligibleAdvisors方法上来
在上文中我们已经说过了所有候选Advisor的获取,下面就要从这些增强中获取可以适用到目标对象的Advisor,跟踪下源码:
ProxyCreationContext.setCurrentProxiedBeanName(beanName);设置了beanName,这里使用了ThreadLocal,用线程对象做key,只可以保存一个值。使用AopUtiles获取适用的Advisor,我们布深究其实现方法,到这里适用的Advisor已经获取到,直接创建代理对象。
回到wrapIfNecessary方法:// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
这里使用了DefaultAopProxyFactory对象来返回代理工具对象,简单来说,就是根据条件决定返回JdkDynamicAopProxy还是ObjenesisCglibAopProxy
然后用返回的代理工具类去实例化目标代理类。先看下JDK代理类型,调用其getProxy方法
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp, MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) { this.declaredPointcut = ajexp; this.method = method; this.atAspectJAdvisorFactory = af; this.aspectInstanceFactory = aif; this.declarationOrder = declarationOrderInAspect; this.aspectName = aspectName; if (aif.getAspectMetadata().isLazilyInstantiated()) { // Static part of the pointcut is a lazy type. Pointcut preInstantiationPointcut = Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. // If it's not a dynamic pointcut, it may be optimized out // by the Spring AOP infrastructure after the first evaluation. this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif); this.lazy = true; } else { // A singleton aspect. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); this.pointcut = declaredPointcut; this.lazy = false; } }
在instantiateAdivice方法中,根据不同的类型创建了不同的Advice对象。
@Override public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // If we get here, we know we have an AspectJ method. // Check that it's an AspectJ-annotated class if (!isAspect(candidateAspectClass)) { throw new AopConfigException("Advice must be declared inside an aspect type: " + "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]"); } if (logger.isDebugEnabled()) { logger.debug("Found AspectJ method: " + candidateAdviceMethod); } AbstractAspectJAdvice springAdvice; switch (aspectJAnnotation.getAnnotationType()) { case AtBefore: springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif); break; case AtAfter: springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif); break; case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; case AtAround: springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif); break; case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; default: throw new UnsupportedOperationException( "Unsupported advice type on method " + candidateAdviceMethod); } // Now to configure the advice... springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrderInAspect); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
我们回到AspectJAwareAdvisorAutoProxyCreator的父类AbstractAdvisorAutoProxyCreator的findEligibleAdvisors方法上来
/** * Find all eligible Advisors for auto-proxying this class. * @param beanClass the clazz to find advisors for * @param beanName the name of the currently proxied bean * @return the empty List, not {@code null}, * if there are no pointcuts or interceptors * @see #findCandidateAdvisors * @see #sortAdvisors * @see #extendAdvisors */ protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
在上文中我们已经说过了所有候选Advisor的获取,下面就要从这些增强中获取可以适用到目标对象的Advisor,跟踪下源码:
/** * Search the given candidate Advisors to find all Advisors that * can apply to the specified bean. * @param candidateAdvisors the candidate Advisors * @param beanClass the target's bean class * @param beanName the target's bean name * @return the List of applicable Advisors * @see ProxyCreationContext#getCurrentProxiedBeanName() */ protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
ProxyCreationContext.setCurrentProxiedBeanName(beanName);设置了beanName,这里使用了ThreadLocal,用线程对象做key,只可以保存一个值。使用AopUtiles获取适用的Advisor,我们布深究其实现方法,到这里适用的Advisor已经获取到,直接创建代理对象。
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
回到wrapIfNecessary方法:// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
/** * Create a new proxy according to the settings in this factory. * <p>Can be called repeatedly. Effect will vary if we've added * or removed interfaces. Can add and remove interceptors. * <p>Uses the given class loader (if necessary for proxy creation). * @param classLoader the class loader to create the proxy with * (or {@code null} for the low-level proxy facility's default) * @return the proxy object */ public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
这里使用了DefaultAopProxyFactory对象来返回代理工具对象,简单来说,就是根据条件决定返回JdkDynamicAopProxy还是ObjenesisCglibAopProxy
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
然后用返回的代理工具类去实例化目标代理类。先看下JDK代理类型,调用其getProxy方法
@Override 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); }
相关文章推荐
- aspnet_regiis.exe -i 报 “此操作系统版本不支持此选项”
- 保护ASP.NET 应用免受 CSRF 攻击
- Aop/AspectJ
- ASPNET 5 和 dnx commands
- ASP.NET html转图片
- ASP.NET 资料下载
- asp.net主题文件(css+.skin)的使用
- 【ASP】英语九百句-ASP输出JSON,AJAX异步请求到本地存储localstorage
- 【ASP】OLEDB方式连接各类数据库(sql,access,excel,txt)
- Microsoft.Aspnet.SingR2实例
- 在asp中,在子页面中如何让服务器控件的id不在运行后改变的方法
- 22、ASP.NET MVC入门到精通——搭建项目框架
- ASP.Net的导出Excel的快速方法,DataTable导出Excel(亲测,非原创)
- ASP.Net MVC跳转,分为form的submit提交跳转和ajax跳转
- Metasploit - Jenkins
- storm 0.10.0 kafkaSpout 总是读取旧消息 offset丢失问题
- Asp.net WebAPI 教程整理
- asp连接acess数据库出现 Microsoft JET Database Engine 错误 '80004005
- Aspera Connect 3.6与Chrome 42以上版本集成杂记
- 在 Mac OS 上创建并运行 ASP.NET Core 1.0 网站