Spring AOP 实现
2016-06-27 21:42
501 查看
Aop是Aspect-Oriented Programming(面向方面编程或面向切面编程)的简称。在Spring平台功能中,AOP是一个核心模块,Spring将AOP框架与IoC容器紧密集成,从而为使用AOP提供最大便利。
AOP可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
Spring AOP实现中,使用Java语言来实现增强对象与切面增强应用,并为这两者的结合提供了配置环境。
1、常用Spring AOP 的两种方式实现
通常使用Spring AOP主要有两种方式,一种是基于xml配置的纯POJO切面方式,另一种是通过@AspectJ注解驱动的切面方式。如果是纯POJO切面的配置AOP,我们需要在Spring容器xml资源定义文件中声明切面bean,并将切面、切点和通知配置信息通过<aop:config>标签加以说明。如果是@AspectJ注解驱动的切面,我们知道为了支持注解,我们需要在配置文件中加入<aop:aspectj-autoproxy
/>标签。不论何种形式,Spring容器在处理切面时的思路是一致的,在Spring容器的初始化过程中,当载入、解析配置文件中的这些标签,都需要动态的通过自定义标签机制解析这些标签,从而生成相应的BeanDefine。
1)Spring Aop 自定义标签处理
在类AopNamespaceHandler中,源码如下:
在init()函数中,注册了ConfigBeanDefinitionParser()用于解析处理纯POJO切面方式<aop:config>标签,然后注册了AspectJAutoProxyBeanDefinitionParser()用于解析处理<aop:aspectj-autoproxy
/>标签。
2)注册Aop自动代理创建器
不管是 ConfigBeanDefinitionParser还是AspectJAutoProxyBeanDefinitionParser,他们都是实现BeanDefinitionParse接口,主要的方法是BeanDefinition parse(Element
element, ParserContext parserContext)。
ConfigBeanDefinitionParser的parse()方法:
在该函数中首先注册AutoProxyCreator,然后根据不同切面元素解析成为响应的BeanDefinition。this.configureAutoProxyCreator(parserContext, element);最终会执行
注册AspectJAwareAdvisorAutoProxyCreator。
AspectJAutoProxyBeanDefinitionParser的parse()方法:
可以看到,同样的注册AspectJAnnotationAutoProxyCreator,不同于之前的是,AspectJAnnotationAutoProxyCreator继承自AspectJAwareAdvisorAutoProxyCreator,添加了对于注解的处理。
3)AutoProxyCreator类继承体系
通过类的继承体系,可以看到AutoProxyCreator类实现了BeanPostProcessor接口,其实际是一
个InstantiationAwareBeanPostProcessor。在bean的生命周期中,可以知道,当容器注册了BeanPostProcessor类型的bean后,从容器中获取任何的bean,都将经过BeanPostProcessor相关方法的处理。那么,当一个bean,被切入切面,进行功能增强时,也是通过InstantiationAwareBeanPostProcessor相关方法对这个bean进行处理,具体就是通过代理方式,将切面植入方法调用流程。而这个处理方法就是 Object
postProcessAfterInitialization(Object bean, String beanName)。
在this.wrapIfNecessary(bean, beanName, cacheKey)中封装bean生成代理对象返回。
4)生成代理相关类继承体系
在生成代理对象时,通过ProxyFactory类Object getProxy(TargetSource targetSource)方法生成,targetSource是被代理的对象bean封装。
最终调用DefaultAopProxyFactory类的AopProxy createAopProxy(AdvisedSupport config)方法:
Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。
而JdkDynamicAopProxy是标准的java动态代理使用方式,可以看到其实现了InvocationHandler接口。在JdkDynamicAopProxy中,通过Object
getProxy(ClassLoader classLoader)函数,获取代理:
我们知道InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。
AOP可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
Spring AOP实现中,使用Java语言来实现增强对象与切面增强应用,并为这两者的结合提供了配置环境。
1、常用Spring AOP 的两种方式实现
通常使用Spring AOP主要有两种方式,一种是基于xml配置的纯POJO切面方式,另一种是通过@AspectJ注解驱动的切面方式。如果是纯POJO切面的配置AOP,我们需要在Spring容器xml资源定义文件中声明切面bean,并将切面、切点和通知配置信息通过<aop:config>标签加以说明。如果是@AspectJ注解驱动的切面,我们知道为了支持注解,我们需要在配置文件中加入<aop:aspectj-autoproxy
/>标签。不论何种形式,Spring容器在处理切面时的思路是一致的,在Spring容器的初始化过程中,当载入、解析配置文件中的这些标签,都需要动态的通过自定义标签机制解析这些标签,从而生成相应的BeanDefine。
1)Spring Aop 自定义标签处理
在类AopNamespaceHandler中,源码如下:
public class AopNamespaceHandler extends NamespaceHandlerSupport { public AopNamespaceHandler() { } public void init() { this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } }
在init()函数中,注册了ConfigBeanDefinitionParser()用于解析处理纯POJO切面方式<aop:config>标签,然后注册了AspectJAutoProxyBeanDefinitionParser()用于解析处理<aop:aspectj-autoproxy
/>标签。
2)注册Aop自动代理创建器
不管是 ConfigBeanDefinitionParser还是AspectJAutoProxyBeanDefinitionParser,他们都是实现BeanDefinitionParse接口,主要的方法是BeanDefinition parse(Element
element, ParserContext parserContext)。
ConfigBeanDefinitionParser的parse()方法:
public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); this.configureAutoProxyCreator(parserContext, element); List childElts = DomUtils.getChildElements(element); Iterator var5 = childElts.iterator(); while(var5.hasNext()) { Element elt = (Element)var5.next(); String localName = parserContext.getDelegate().getLocalName(elt); if("pointcut".equals(localName)) { this.parsePointcut(elt, 4000 parserContext); } else if("advisor".equals(localName)) { this.parseAdvisor(elt, parserContext); } else if("aspect".equals(localName)) { this.parseAspect(elt, parserContext); } } parserContext.popAndRegisterContainingComponent(); return null; }
在该函数中首先注册AutoProxyCreator,然后根据不同切面元素解析成为响应的BeanDefinition。this.configureAutoProxyCreator(parserContext, element);最终会执行
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); }
注册AspectJAwareAdvisorAutoProxyCreator。
AspectJAutoProxyBeanDefinitionParser的parse()方法:
public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); this.extendBeanDefinition(element, parserContext); return null; } public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); }
可以看到,同样的注册AspectJAnnotationAutoProxyCreator,不同于之前的是,AspectJAnnotationAutoProxyCreator继承自AspectJAwareAdvisorAutoProxyCreator,添加了对于注解的处理。
3)AutoProxyCreator类继承体系
通过类的继承体系,可以看到AutoProxyCreator类实现了BeanPostProcessor接口,其实际是一
个InstantiationAwareBeanPostProcessor。在bean的生命周期中,可以知道,当容器注册了BeanPostProcessor类型的bean后,从容器中获取任何的bean,都将经过BeanPostProcessor相关方法的处理。那么,当一个bean,被切入切面,进行功能增强时,也是通过InstantiationAwareBeanPostProcessor相关方法对这个bean进行处理,具体就是通过代理方式,将切面植入方法调用流程。而这个处理方法就是 Object
postProcessAfterInitialization(Object bean, String beanName)。
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean != null) { Object cacheKey = this.getCacheKey(bean.getClass(), beanName); if(!this.earlyProxyReferences.contains(cacheKey)) { return this.wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
在this.wrapIfNecessary(bean, beanName, cacheKey)中封装bean生成代理对象返回。
4)生成代理相关类继承体系
在生成代理对象时,通过ProxyFactory类Object getProxy(TargetSource targetSource)方法生成,targetSource是被代理的对象bean封装。
public static Object getProxy(TargetSource targetSource) { if(targetSource.getTargetClass() == null) { throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class"); } else { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetSource(targetSource); proxyFactory.setProxyTargetClass(true); return proxyFactory.getProxy(); } }
最终调用DefaultAopProxyFactory类的AopProxy createAopProxy(AdvisedSupport config)方法:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if(!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) { return new JdkDynamicAopProxy(config); } else { 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."); } else { return (AopProxy)(targetClass.isInterface()?new JdkDynamicAopProxy(config):new ObjenesisCglibAopProxy(config)); } } }
Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。
而JdkDynamicAopProxy是标准的java动态代理使用方式,可以看到其实现了InvocationHandler接口。在JdkDynamicAopProxy中,通过Object
getProxy(ClassLoader classLoader)函数,获取代理:
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); this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
我们知道InvocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; Object retVal; try { //eqauls()方法,具目标对象未实现此方法 if(!this.equalsDefined && AopUtils.isEqualsMethod(method)) { Boolean retVal2 = Boolean.valueOf(this.equals(args[0])); return retVal2; } //hashCode()方法,具目标对象未实现此方法 if(!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { Integer retVal1 = Integer.valueOf(this.hashCode()); return retVal1; } //Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知 if(this.advised.opaque || !method.getDeclaringClass().isInterface() || !method.getDeclaringClass().isAssignableFrom(Advised.class)) { if(this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //获得目标对象的类 target = targetSource.getTarget(); if(target != null) { targetClass = target.getClass(); } //获取可以应用到此方法上的Interceptor列表 <strong> List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);</strong> if(chain.isEmpty()) { //如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args) retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { //创建MethodInvocation ,封装 Interceptor调用链 ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //调用proceed()方法, 依次执行 Interceptor调用链 <strong>retVal = invocation.proceed();</strong> } 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); } Object var13 = retVal; return var13; } retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } finally { if(target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if(setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } return retVal; }
通过this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)方法,获取通知拦截器链
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) { //这里使用了cache,利用cache获取已经有了的intercepter AdvisedSupport.MethodCacheKey cacheKey = new AdvisedSupport.MethodCacheKey(method); List cached = (List)this.methodCache.get(cacheKey); if(cached == null) { //这里是利用DefaultAdvisorChainFactory,获取intercepter链 cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass); this.methodCache.put(cacheKey, cached); } return cached; }在DefaultAdvisorChainFactory类(生成连接器的工厂)中:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass) { ArrayList interceptorList = new ArrayList(config.getAdvisors().length); Class actualClass = targetClass != null?targetClass:method.getDeclaringClass(); boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] var8 = config.getAdvisors(); int var9 = var8.length; for(int var10 = 0; var10 < var9; ++var10) { Advisor advisor = var8[var10]; MethodInterceptor[] interceptors1; if(advisor instanceof PointcutAdvisor) { PointcutAdvisor interceptors = (PointcutAdvisor)advisor; if(config.isPreFiltered() || interceptors.getPointcut().getClassFilter().matches(actualClass)) { interceptors1 = registry.getInterceptors(advisor); MethodMatcher mm = interceptors.getPointcut().getMethodMatcher(); if(MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { if(mm.isRuntime()) { MethodInterceptor[] var15 = interceptors1; int var16 = interceptors1.length; for(int var17 = 0; var17 < var16; ++var17) { MethodInterceptor interceptor = var15[var17]; interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors1)); } } } } else if(advisor instanceof IntroductionAdvisor) { IntroductionAdvisor var19 = (IntroductionAdvisor)advisor; if(config.isPreFiltered() || var19.getClassFilter().matches(actualClass)) { interceptors1 = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors1)); } } else { MethodInterceptor[] var20 = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(var20)); } } return interceptorList; }在这个函数中,首先设置一个List,用于保存最后返回的interceptorList, 然后DefaultAdvisorChainFactory会通过一个AdvisorAdapterRegistry 来实现拦截器的注册,将配置中Advice适配包装为interceptor,最终返回。
通过 GlobalAdvisorAdapterRegistry.getInstance()获取
AdvisorAdapterRegistry registry。
GlobalAdvisorAdapterRegistry运用单例模式:其实例是DefaultAdvisorAdapterRegistry类对象:
public abstract class GlobalAdvisorAdapterRegistry { private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry(); public GlobalAdvisorAdapterRegistry() { } public static AdvisorAdapterRegistry getInstance() { return instance; } static void reset() { instance = new DefaultAdvisorAdapterRegistry(); } }
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { private final List<AdvisorAdapter> adapters = new ArrayList(3); public DefaultAdvisorAdapterRegistry() { this.registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); this.registerAdvisorAdapter(new AfterReturningAdviceAdapter()); this.registerAdvisorAdapter(new ThrowsAdviceAdapter()); } public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if(adviceObject instanceof Advisor) { return (Advisor)adviceObject; } else if(!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } else { Advice advice = (Advice)adviceObject; if(advice instanceof MethodInterceptor) { return new DefaultPointcutAdvisor(advice); } else { Iterator var3 = this.adapters.iterator(); AdvisorAdapter adapter; do { if(!var3.hasNext()) { throw new UnknownAdviceTypeException(advice); } adapter = (AdvisorAdapter)var3.next(); } while(!adapter.supportsAdvice(advice)); return new DefaultPointcutAdvisor(advice); } } } public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { ArrayList interceptors = new ArrayList(3); Advice advice = advisor.getAdvice(); if(advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor)advice); } Iterator var4 = this.adapters.iterator(); while(var4.hasNext()) { AdvisorAdapter adapter = (AdvisorAdapter)var4.next(); if(adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if(interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } else { return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[interceptors.size()]); } } public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); } }
相关文章推荐
- Spring AOP动态代理-切面
- yui3的AOP(面向切面编程)和OOP(面向对象编程)
- JavaScript AOP编程实例
- 使用AOP改善javascript代码
- 初识SmartJS - AOP三剑客
- java使用动态代理来实现AOP(日志记录)的实例代码
- JavaScript之AOP编程实例
- Javascript aop(面向切面编程)之around(环绕)分析
- php笔记之:AOP的应用
- 深入浅析Spring 的aop实现原理
- spring aop两种配置方式
- 实例讲解Java的Spring框架中的AOP实现
- Java的Spring框架中AOP项目的一般配置和部署教程
- Java实现AOP面向切面编程的实例教程
- 举例讲解Java的Spring框架中AOP程序设计方式的使用
- autoload-cache-1.7 发布
- autoload-cache-2.4 发布
- Spring AOP嵌套调用的问题 (同一类方法内调用切面切不到)
- Spring3 AOP配置异常。执行时间记录