Spring源码学习之AOP
来源:互联网 发布:淘宝达人账号如何注销 编辑:程序博客网 时间:2024/05/17 02:09
我们都站在巨人的肩膀上
声明:参考《spring源码深度解析》
1.Spring AOP主要采用动态代理实现,而动态代理分为两种:
- JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行时期创建一个接口的实现类来完成对目标对象的代理。
- CGLIB代理:实现原理类似于JDK动态代理,只是他在运行期间生产的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层依靠ASM操作字节码实现,性能比JDK强。
具体请参考:http://blog.csdn.net/u012342524/article/details/56676871
2.创建代理主要包含两步骤:
1. 获取增强方法或者增强器
2. 根据获取的增强器进行代理
- 首先来看Spring如何获取增强器:
- 获取所有的beanName,这一步骤中所有的在beanFacotry中注册的Bean都会被提取出来。
- 遍历所有的beanName,并找出声明AspectJ注解的类,进行进一步的处理。
- 对标记为AspectJ注解的类进行增强器的提取。
- 将提取结果加入缓存。
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = null; synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); //获取所有的beanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); //循环找出所有beanName的增强方法 for (String beanName : beanNames) { //不合法的bean则略过,由子类定义规则,默认返回true if (!isEligibleBean(beanName)) { continue; } //获取对应的bean的类型 Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } //如果存在Aspect注解 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //解析标记AspectJ注解中的增强方法 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } //记录在缓存中 List<Advisor> advisors = new LinkedList<Advisor>(); for (String aspectName : aspectNames) { List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } return advisors; }
核心提取方法getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) { //获取标记为AspectJ的类 final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass(); //获取标记为AspectJ的name final String aspectName = maaif.getAspectMetadata().getAspectName(); //验证 validate(aspectClass); final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(maaif); final List<Advisor> advisors = new LinkedList<Advisor>(); for (Method method : getAdvisorMethods(aspectClass)) { Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { //如果寻找的增强器不为空而且又配置了增强延迟初始化那么需求在首位加入同步实例化增强器 Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } //获取DeclareParent注解 for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; }
Spring会根据注解类型不同封装不同的增强器
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 (!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; }
- 寻找匹配的增强器
前面提取的增强器并不一定符合所有的bean,我们还会配置通配符的增强器
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
findAdvisorsThatCanApply 函数主要功能是寻找所有增强器中适用于当前class的增强器。引介增强与普通的增强是处理不一样的,所以分开处理。真正的匹配在canApply中实现。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { Method[] methods = clazz.getMethods(); for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
- 创建代理
获取到所有对应的bean的增强器后,可以进行代理的创建了。
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); //获取当前类中相关属性 proxyFactory.copyFrom(this); //决定对于给定的bean是否应该使用targetClass而不是他的接口代理 //检查proxyTargeClass设置以及preserveTargetClass属性 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); //用来控制代理工厂被配置之后,是否允许修改通知 //缺省值为false(即在代理被配置之后,不允许修改代理的配置) proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
对于代理类的创建及处理,Spring委托给了ProxyFactory去处理,而在此函数中主要是对ProxyFactory的初始化操作,进而对真正的创建代理做准备,这些初始化操作包括如下内容。
1. 获取当前类中的属性
2. 添加代理接口
3. 封装Advisor并加入到ProxyFactory中
4. 设置要代理的类
5. 当然在Spring中还为子类提供了定制的函数customizeProxyFactory,子类可以在此函数中进行对ProxyFactory的进一步封装
6. 进行获取代理操作
而真正在创建代理的是createAopProxy,如下:
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } //创建代理 return getAopProxyFactory().createAopProxy(this);}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()) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); }}
JdkDynamicAopProxy继承了InvocationHandler,核心代码写在了invoke中
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0]); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return hashCode(); } if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; 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(); } Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } }
0 0
- Spring源码学习之AOP
- spring源码学习之路---AOP初探
- Spring源码学习之认识AOP
- Spring源码之AOP
- Spring Aop源码学习--Aop代理AopProxy
- Spring学习之AOP
- Spring学习之AOP
- 【Spring学习】之 AOP
- Spring学习之AOP
- Spring学习之AOP
- spring之AOP学习
- Spring学习之AOP
- spring源码学习之路---AOP初探(六)
- spring源码学习之路---深入AOP(终)
- spring源码学习之路---AOP初探(六)
- spring源码学习之路---深入AOP(终)
- spring源码学习之路---深入AOP(终)
- spring源码分析之aop
- Linux下安装TFTP服务的具体操作
- C# 发起普通http请求
- iOS多个网络请求问题
- HDU 1078 FatMouse and Cheese
- #!/usr/bin/env python的作用
- Spring源码学习之AOP
- 运维笔记31 (pacemaker高可用集群搭建的总结)
- LeetCode-496. Next Greater Element I
- Android Material Design -TextInputLayout
- 公众号第三方平台和微信公众号平台的区别与开发步骤
- 程序中乱码解决方案
- 集合各实现类的底层实现原理
- 设置mysql远程链接
- Redis设计思路学习与总结