Spring AOP的实现

Aspectj:源代码和字节码级别的编织器,用户需要使用不同于Java的新语言。
AspectWerkz:AOP框架,使用字节码动态编织器和XML配置。
JBoss-AOP:基于拦截器和元数据的AOP框架,运行在JBoss应用服务器上。以及在AOP中用到的一些相关的技术实现。
BCEL:java字节码操作类库。
Javassist:Java字节码操作类库,JBoss的一个子项目。


三种织入方式:编译期织入、类加载期织入和运行期织入。
编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;
而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;
运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。


AspectJ采用编译期织入和类加载期织入的方式织入切面,是语言级的AOP实现,提供了完备的AOP支持。它用AspectJ语言定义切面,在编译期或类加载期将切面织入到Java类中。 


Spring AOP的实现和其他特性的实现一样,除了可以使用Spring本身提供的AOP实现之外,还封装了业界优秀的AOP解决方案Aspectj来供应用使用。




Advice通知:
Advice定义在连接点做什么,为切面增强提供织入接口。
Advice是AOP联盟定义的一个接口,org.aopalliance.aop.Advice。
在Spring AOP实现中,使用了这个统一接口,并通过这个接口,为AOP切面增强了织入功能做了很多的细化和扩展,比如提供了更具体的通知类型,如BeforeAdvice、AfterAdvice、ThrowsAdvice等。
BeforeAdvice又演变出子接口MethodBeforeAdvice,有一个方法before,具体什么意思也不用多说。
AfterAdvice演变子接口AfterReturningAdvice,有一个方法afterReturning。
ThrowsAdvice并没有指定接口方法,但是你可以看到他继承自AfterAdvice。


Pointcut切点:
Pointcut来定义需要增强的方法的集合。
Pointcut要返回一个MethodMatcher来判断是否需要对方法调用进行增强。
其中的一个实现JdkRegexpMethodPointcut,完成了通过正则表达式完成了对方法名进行匹配的功能。
而且JdkRegexpMethodPointcut还实现了MethodMatcher接口。
JdkRegexpMethodPointcut中实现了AbstractRegexpMethodPointcut中的抽象方法matches,并用jdk的正则表达式完成匹配。


Advisor通知器:
完成对目标的切面设计Advice和关注点设计Pointcut以后,需要一个对象把他们结合起来。
DefaultPointcutAdvisor-
public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) {
this.pointcut = pointcut;
setAdvice(advice);
}
类中还有个TruePointcut的单例默认值,一直返回true。


上面提到的几个类实现都非常简单,因为,他们基本就只是属于一个“数据形式的定义”。




AOP简介 
通知(Advice):通知定义了切面是什么以及何时使用。除了要描述切面要完成的工作,通知还解决了何时执行这个工作的问题。 
连接点(Joinpoint):连接点是在程序执行过程中能够插入切面的一个点。这个点可以是方法被调用时、异常被抛出时、甚至字段被编辑时。切面代码可以通过这些点插入到程序的一般流程之中,从而添加新的行为。 
切入点(Poincut):切入点可以缩小切面通知的连接点的范围。如果说通知定义了切面的“什么”和“何时”,那么切入点就定义了“何地”。 
切面(Aspect):切面是通知和切入点的组合。 
引入(Introduction):“引入”允许我们向现有的类添加新方法或者属性。 
目标(Target):被通知的对象。 
代理(Proxy):是向目标对象应用通知之后被创建的对象。 
织入(Weaving):是把切面应用到目标对象来创建新的代理对象的过程。编译时、类加载时、运行时。


在Spring AOP实现中,使用的核心技术是动态代理。
通过JDK的动态代理特性,可以为任意Java对象创建代理对象,这个特性是通过Java Reflection API来完成的。
相反Spring AOP还将ApsectJ集成了进来。
这个代理对象可以通过使用JDK的proxy来完成,也可以通过第三方的类生成器CGLIB来完成。




接口org.springframework.beans.factory.FactoryBean<T>:
做为bean的创建的一个工厂,通过是三个方法T getObject() 、Class<?> getObjectType()、boolean isSingleton()可以看出,实现他可以作为一个bean创建的代理对象返回。


首先FactoryBean是我们的主接口,这里面的定义就是我们需要的结果,但是下面会围绕这个接口定义了一些列接口,包括资源、“算法”等操作,最终得到我们这个接口想要的东西。


----------------资源相关Aware--------------


接口org.springframework.beans.factory.Aware:
本接口没有定义任何方法,只是 作为一个超类接口存在;Marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method. 


接口org.springframework.beans.factory.BeanFactoryAware:
继承Aware
就一个方法void setBeanFactory(BeanFactory beanFactory),定义了BeanFactory的回调注入。


接口org.springframework.beans.factory.BeanClassLoaderAware:
继承Aware
一个方法void setBeanClassLoader(ClassLoader classLoader),定义ClassLoader的回调注入。


接口org.springframework.aop.TargetClassAware:
没有继承自Aware,上面的Aware是bean相关的。这个是aop相关的。
定义一个方法Class<?> getTargetClass(),目标类获取。就是我们配置里面的<property name="target" ref="..."></property>




-----------------Advised--------------------
接口org.springframework.aop.framework.Advised:
和名字一样,Advised想干的一些资源管理。


org.springframework.aop.framework.ProxyConfig:
一些标识的存放,保证一致性。


org.springframework.aop.framework.AdvisedSupport:
Advised的实现支持类,包括对各种配置资源的管理。从调用本类的参数命名定义上AdvisedSupport config,可以知道本类就是一个资源的快照类。


org.springframework.aop.framework.ProxyCreatorSupport:
Base class for proxy factories. Provides convenient access to a configurable AopProxyFactory.
真正的创建是在AopProxy的两个是实现,对AopProxy实现的判断提供是在于AopProxyFactory,本类就是对AopProxyFactory的提供(不是AopProxyFactory的实现是提供)。
/**
* Create a new ProxyCreatorSupport instance.
*/
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
因为本类也继承自AdvisedSupport,包含了各种所需资源。




------------------最终的创建:AopProxy---------------------
接口org.springframework.aop.framework.AopProxy:
Delegate interface for a configured AOP proxy, allowing for the creation of actual proxy objects. 
两个方法Object getProxy()、Object getProxy(ClassLoader classLoader)。


AopProxy的两个重要实现Cglib2AopProxy、JdkDynamicAopProxy,也是我们最终产生AOP后的对象的地方。


接口org.springframework.aop.framework.AopProxyFactory:
整理结合需要创建AopProxy资源的地方,也是判断到底返回什么AopProxy实现类型的地方。


org.springframework.aop.framework.DefaultAopProxyFactory:
AopProxyFactory的唯一默认实现。以后我们如果想单独加入AopProxy的底层实现方式,可以从这里着手。




org.springframework.aop.framework.ProxyFactoryBean:
最终的出口



设计原理:
ProxyFactoryBean中,封装了主要代理对象的生成过程。在这个生成过程中,可以使用JDK的Proxy和CGLIB两种生成方式。
完成AOP应用的类,比如AspectJProxyFactory、ProxyFactory和ProxyFactoryBean,他们都在统一个类的继承体系下,都是ProxyConfig、AdvisedSupport和ProxyCreatorSupport的子类。
作为共同基类,可以将ProxyConfig看成是一个数据基类,这个数据基类为ProxyFactoryBean这样的子类提供了配置属性;
在另一个基类AdvisedSupport的实现中,封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象的创建,AdvisedSupport把他交给他的子类们去完成;
对于ProxyCreatorSupport,可以将它看成是其子类创建AOP代理对象的一个辅助类。




使用ProxyFactoryBean: 
代理(Proxy):是向目标对象应用通知之后被创建的对象 
利用ProxyFactoryBean代理被切面的对象。

[java]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.        xmlns:aop="http://www.springframework.org/schema/aop"    
  5.        xsi:schemaLocation="    
  6.             http://www.springframework.org/schema/beans    
  7.             http://www.springframework.org/schema/beans/spring-beans.xsd    
  8.             http://www.springframework.org/schema/aop    
  9.             http://www.springframework.org/schema/aop/spring-aop.xsd">    
  10.     
  11.     <bean id="audience" class="cn.partner4java.springidol.Audience"/>    
  12.         
  13.     <!-- 通知(Advice):通知定义了切面是什么以及何时使用 -->    
  14.     <bean id="advice1" class="cn.partner4java.springidol.AudienceAdvice">    
  15.         <property name="audience" ref="audience"></property>    
  16.     </bean>    
  17.     <bean id="advice2" class="cn.partner4java.springidol.AudienceAroundAdvice">    
  18.         <property name="audience" ref="audience"></property>    
  19.     </bean>    
  20.         
  21.         
  22.     <!-- 切入点(Poincut):切入点可以缩小切面通知的连接点的范围 -->    
  23.     <bean id="performancePointcut1" class="org.springframework.aop.support.JdkRegexpMethodPointcut">    
  24.         <property name="pattern" value=".*perform"></property>    
  25.     </bean>    
  26.     <!-- 定义AspectJ方式切点 -->    
  27.     <bean id="performancePointcut2" class="org.springframework.aop.aspectj.AspectJExpressionPointcut">    
  28.         <property name="expression" value="execution(* Performer+.perform(..))"></property>    
  29.     </bean>    
  30.         
  31.         
  32.     <!-- 切面(Aspect):切面是通知和切入点的组合  (通知者)-->    
  33.     <bean id="audienceAdvisor1" class="org.springframework.aop.support.DefaultPointcutAdvisor">    
  34.         <property name="advice" ref="advice1"></property>    
  35.         <property name="pointcut" ref="performancePointcut1"></property>    
  36.     </bean>    
  37.     <bean id="audienceAdvisor2" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">    
  38.         <property name="advice" ref="advice1"></property>    
  39.         <property name="pattern" value=".*perform"></property>    
  40.     </bean>    
  41.         
  42.         
  43.     <!-- 使用ProxyFactoryBean -->    
  44.     <bean id="performer" class="cn.partner4java.springidol.PerformerBean"></bean>    
  45.         
  46.     <bean id="duke" class="org.springframework.aop.framework.ProxyFactoryBean">    
  47.         <property name="target" ref="performer"></property>    
  48.         <property name="interceptorNames" value="audienceAdvisor1"></property>    
  49.         <property name="proxyInterfaces" value="cn.partner4java.springidol.Performer"></property>    
  50.     </bean>    
  51.         
  52. </beans>    

[java]  view plain copy
  1. 调用:  
  2. package cn.partner4java.springidol;    
  3.     
  4. import org.springframework.context.ApplicationContext;    
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;    
  6.     
  7. public class HelloWorld {    
  8.     
  9.     public static void main(String[] args) {    
  10.         ApplicationContext ctx = new ClassPathXmlApplicationContext(    
  11.                     "/META-INF/spring/springido.xml");    
  12.             
  13.         Performer performer = (Performer) ctx.getBean("duke");    
  14.         performer.perform();    
  15.     }    
  16.     
  17. }    
  18.   
  19.   
  20.   
  21. ProxyFactoryBean生成AopProxy代理对象:  
  22.     /** 
  23.      * Return a proxy. Invoked when clients obtain beans from this factory bean. 
  24.      * Create an instance of the AOP proxy to be returned by this factory. 
  25.      * The instance will be cached for a singleton, and create on each call to 
  26.      * <code>getObject()</code> for a proxy. 
  27.      * @return a fresh AOP proxy reflecting the current state of this factory 
  28.      */  
  29.     public Object getObject() throws BeansException {  
  30.         //这里初始化通知器链  
  31.         initializeAdvisorChain();  
  32.         //这里对singleton和prototype的类型进行区分,生成对应的proxy  
  33.         if (isSingleton()) {  
  34.             return getSingletonInstance();  
  35.         }  
  36.         else {  
  37.             if (this.targetName == null) {  
  38.                 logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +  
  39.                         "Enable prototype proxies by setting the 'targetName' property.");  
  40.             }  
  41.             return newPrototypeInstance();  
  42.         }  
  43.     }  
  44.   
  45. ProxyFactoryBean的AOP实现需要依赖JDK或者CGLIB提供的Proxy特性。  
  46. 从FactoryBean中获取对象,是以getObject方法作为入口完成的。  
  47.     /** 
  48.      * Create the advisor (interceptor) chain. Aadvisors that are sourced 
  49.      * from a BeanFactory will be refreshed each time a new prototype instance 
  50.      * is added. Interceptors added programmatically through the factory API 
  51.      * are unaffected by such changes. 
  52.      */  
  53.     private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {  
  54.         if (this.advisorChainInitialized) {  
  55.             return;  
  56.         }  
  57.   
  58.         if (!ObjectUtils.isEmpty(this.interceptorNames)) {  
  59.             if (this.beanFactory == null) {  
  60.                 throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +  
  61.                         "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));  
  62.             }  
  63.   
  64.             // Globals can't be last unless we specified a targetSource using the property...  
  65.             if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&  
  66.                     this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {  
  67.                 throw new AopConfigException("Target required after globals");  
  68.             }  
  69.   
  70.             //这里是添加Advisor链的调用,是通过interceptorNames属性进行配置的  
  71.             // Materialize interceptor chain from bean names.  
  72.             for (String name : this.interceptorNames) {  
  73.                 if (logger.isTraceEnabled()) {  
  74.                     logger.trace("Configuring advisor or advice '" + name + "'");  
  75.                 }  
  76.   
  77.                 if (name.endsWith(GLOBAL_SUFFIX)) {  
  78.                     if (!(this.beanFactory instanceof ListableBeanFactory)) {  
  79.                         throw new AopConfigException(  
  80.                                 "Can only use global advisors or interceptors with a ListableBeanFactory");  
  81.                     }  
  82.                     addGlobalAdvisor((ListableBeanFactory) this.beanFactory,  
  83.                             name.substring(0, name.length() - GLOBAL_SUFFIX.length()));  
  84.                 }  
  85.   
  86.                 else {  
  87.                     //如果程序在这里被调用,那么需要加入命名的拦截器advice,并且需要检查这个Bean是singleton还是prototype类型  
  88.                     // If we get here, we need to add a named interceptor.  
  89.                     // We must check if it's a singleton or prototype.  
  90.                     Object advice;  
  91.                     if (this.singleton || this.beanFactory.isSingleton(name)) {  
  92.                         // Add the real Advisor/Advice to the chain.  
  93.                         advice = this.beanFactory.getBean(name);  
  94.                     }  
  95.                     else {  
  96.                         // It's a prototype Advice or Advisor: replace with a prototype.  
  97.                         // Avoid unnecessary creation of prototype bean just for advisor chain initialization.  
  98.                         advice = new PrototypePlaceholderAdvisor(name);  
  99.                     }  
  100.                     addAdvisorOnChainCreation(advice, name);  
  101.                 }  
  102.             }  
  103.         }  
  104.   
  105.         this.advisorChainInitialized = true;  
  106.     }  
  107.   
  108. 生成Singleton的代理对象在getSingletonInstance()的代码中完成,这个方法是ProxyFactoryBean生成AopProxy代理对象的调用入口。  
  109.     /** 
  110.      * Return the singleton instance of this class's proxy object, 
  111.      * lazily creating it if it hasn't been created already. 
  112.      * @return the shared singleton proxy 
  113.      */  
  114.     private synchronized Object getSingletonInstance() {  
  115.         if (this.singletonInstance == null) {  
  116.             this.targetSource = freshTargetSource();  
  117.             if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {  
  118.                 //根据AOP框架来判断需要代理的接口  
  119.                 // Rely on AOP infrastructure to tell us what interfaces to proxy.  
  120.                 Class targetClass = getTargetClass();  
  121.                 if (targetClass == null) {  
  122.                     throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");  
  123.                 }  
  124.                 //这里设置代理对象的接口  
  125.                 setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));  
  126.             }  
  127.             // Initialize the shared singleton instance.  
  128.             super.setFrozen(this.freezeProxy);  
  129.             //注意这里的方法会使用ProxyFactory来生成需要的Proxy  
  130.             this.singletonInstance = getProxy(createAopProxy());  
  131.         }  
  132.         return this.singletonInstance;  
  133.     }     
  134.   
  135.     /** 
  136.      * Return the proxy object to expose. 
  137.      * <p>The default implementation uses a <code>getProxy</code> call with 
  138.      * the factory's bean class loader. Can be overridden to specify a 
  139.      * custom class loader. 
  140.      * @param aopProxy the prepared AopProxy instance to get the proxy from 
  141.      * @return the proxy object to expose 
  142.      * @see AopProxy#getProxy(ClassLoader) 
  143.      */  
  144.      //通过createAopProxy返回的AopProxy来得到代理对象  
  145.     protected Object getProxy(AopProxy aopProxy) {  
  146.         return aopProxy.getProxy(this.proxyClassLoader);  
  147.     }  
  148.   
  149. AOP是一个接口,他由两个子类实现,Cglib2AopProxy和JdkDynamicAopProxy。      
  150. 具体的代理对象的生成,是在ProxyFactoryBean的基类AdvisedSupport的实现中借助AopProxyFactory完成的。  
  151. ProxyCreatorSupport:  
  152.     /** 
  153.      * Subclasses should call this to get a new AOP proxy. They should <b>not</b> 
  154.      * create an AOP proxy with <code>this</code> as an argument. 
  155.      */  
  156.     protected final synchronized AopProxy createAopProxy() {  
  157.         if (!this.active) {  
  158.             activate();  
  159.         }  
  160.         //通过AopProxyFactory取得AopProxy,这个AopProxyFactory是在初始化中定义的,默认使用的是DefaultAopProxyFactory  
  161.         return getAopProxyFactory().createAopProxy(this);  
  162.     }  
  163.       
  164. 对具体的实现层次的代理对象的生成,是由Spring封装的CglibProxyFactory和JdkDynamicAopProxy类来完成的。  
  165.   
  166. 在DefaultAopProxyFactory中创建AopProxy:   
  167.     public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {  
  168.         if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {  
  169.             Class targetClass = config.getTargetClass();  
  170.             if (targetClass == null) {  
  171.                 throw new AopConfigException("TargetSource cannot determine target class: " +  
  172.                         "Either an interface or a target is required for proxy creation.");  
  173.             }  
  174.             //如果targetClass是接口类,使用JDK来生成Proxy  
  175.             if (targetClass.isInterface()) {  
  176.                 return new JdkDynamicAopProxy(config);  
  177.             }  
  178.             if (!cglibAvailable) {  
  179.                 throw new AopConfigException(  
  180.                         "Cannot proxy target class because CGLIB2 is not available. " +  
  181.                         "Add CGLIB to the class path or specify proxy interfaces.");  
  182.             }  
  183.             //如果不是接口类生成Proxy,那么使用CGLIB来生成  
  184.             return CglibProxyFactory.createCglibProxy(config);  
  185.         }  
  186.         else {  
  187.             return new JdkDynamicAopProxy(config);  
  188.         }  
  189.     }  
  190.       
  191.       
  192. JDK生成AopProxy代理对象:  
  193. JdkDynamicAopProxy--getProxy  
  194.     public Object getProxy(ClassLoader classLoader) {  
  195.         if (logger.isDebugEnabled()) {  
  196.             logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());  
  197.         }  
  198.         Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);  
  199.         findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);  
  200.         //很熟悉的方式  
  201.         return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  
  202.     }  
  203.   
  204.       
  205. CGLIB生成AopProxy代理对象:  
  206. Cglib2AopProxy--getProxy  
  207.     public Object getProxy(ClassLoader classLoader) {  
  208.         if (logger.isDebugEnabled()) {  
  209.             logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource());  
  210.         }  
  211.         //从advised中取得在IoC容器中配置target对象  
  212.         try {  
  213.             Class rootClass = this.advised.getTargetClass();  
  214.             Assert.state(rootClass != null"Target class must be available for creating a CGLIB proxy");  
  215.   
  216.             Class proxySuperClass = rootClass;  
  217.             if (ClassUtils.isCglibProxyClass(rootClass)) {  
  218.                 proxySuperClass = rootClass.getSuperclass();  
  219.                 Class[] additionalInterfaces = rootClass.getInterfaces();  
  220.                 for (Class additionalInterface : additionalInterfaces) {  
  221.                     this.advised.addInterface(additionalInterface);  
  222.                 }  
  223.             }  
  224.   
  225.             // Validate the class, writing log messages as necessary.  
  226.             validateClassIfNecessary(proxySuperClass);  
  227.   
  228.             //验证代理对象的接口设置  
  229.             //创建并配置CGLIB的Enhancer,这个Enhancer对象是CGLIB的主要操作类  
  230.             // Configure CGLIB Enhancer...  
  231.             Enhancer enhancer = createEnhancer();  
  232.             if (classLoader != null) {  
  233.                 enhancer.setClassLoader(classLoader);  
  234.                 if (classLoader instanceof SmartClassLoader &&  
  235.                         ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {  
  236.                     enhancer.setUseCache(false);  
  237.                 }  
  238.             }  
  239.             //设置Enhancer对象,包括设置代理接口,回调方法  
  240.             //来自advised的IoC配置,比如使用AOP的DynamicAdvisedInterceptor拦截器  
  241.             enhancer.setSuperclass(proxySuperClass);  
  242.             enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));  
  243.             enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));  
  244.             enhancer.setInterceptDuringConstruction(false);  
  245.   
  246.             Callback[] callbacks = getCallbacks(rootClass);  
  247.             enhancer.setCallbacks(callbacks);  
  248.             enhancer.setCallbackFilter(new ProxyCallbackFilter(  
  249.                     this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));  
  250.   
  251.             Class[] types = new Class[callbacks.length];  
  252.             for (int x = 0; x < types.length; x++) {  
  253.                 types[x] = callbacks[x].getClass();  
  254.             }  
  255.             enhancer.setCallbackTypes(types);  
  256.   
  257.             //通过Enhancer生成代理对象  
  258.             // Generate the proxy class and create a proxy instance.  
  259.             Object proxy;  
  260.             if (this.constructorArgs != null) {  
  261.                 proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);  
  262.             }  
  263.             else {  
  264.                 proxy = enhancer.create();  
  265.             }  
  266.   
  267.             return proxy;  
  268.         }  
  269.         catch (CodeGenerationException ex) {  
  270.             throw new AopConfigException("Could not generate CGLIB subclass of class [" +  
  271.                     this.advised.getTargetClass() + "]: " +  
  272.                     "Common causes of this problem include using a final class or a non-visible class",  
  273.                     ex);  
  274.         }  
  275.         catch (IllegalArgumentException ex) {  
  276.             throw new AopConfigException("Could not generate CGLIB subclass of class [" +  
  277.                     this.advised.getTargetClass() + "]: " +  
  278.                     "Common causes of this problem include using a final class or a non-visible class",  
  279.                     ex);  
  280.         }  
  281.         catch (Exception ex) {  
  282.             // TargetSource.getTarget() failed  
  283.             throw new AopConfigException("Unexpected AOP exception", ex);  
  284.         }  
  285.     }     

在这些callback回调中,对已AOP实现,是通过DynamicAdvisedInterceptor来完成的,回调入口是intercept方法。




可以把AOP的实现部分看成由基础设施设备和AOP运行辅助这两个部分组成,这里的AopProxy代理对象的生成,可以看做是一个AOP基础设施的建设过程。
通过这个准备过程,把代理对象、拦截器这些待调用的部门都准备好,等待AOP运行过程中对这些基础设施的使用。
对于应用出发AOP应用,会涉及AOP框架的运行和对AOP基础设施的使用。
这些动态的运行部分,是从前面提到的拦截器回调入口开始的,原理就是各种实现方案。


[java]  view plain copy
  1. 在Spring AOP通过JDK的Proxy方式或者CGLIB方式生成代理对象的时候,相关的拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过对这些方法的回调的来完成。  
  2.   
  3. 来看看AopProxy代理对象的拦截机制是怎样发挥作用和实现AOP功能的:  
  4.   
  5. JdkDynamicAopProxy的invoke拦截:  
  6. final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable :  
  7.   
  8.     /** 
  9.      * Implementation of <code>InvocationHandler.invoke</code>. 
  10.      * <p>Callers will see exactly the exception thrown by the target, 
  11.      * unless a hook method throws an exception. 
  12.      */  
  13.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  14.         MethodInvocation invocation;  
  15.         Object oldProxy = null;  
  16.         boolean setProxyContext = false;  
  17.   
  18.         TargetSource targetSource = this.advised.targetSource;  
  19.         Class targetClass = null;  
  20.         Object target = null;  
  21.   
  22.         try {  
  23.             if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {  
  24.                 //如果目标对象没有实现Object类的基本方法:equals  
  25.                 // The target does not implement the equals(Object) method itself.  
  26.                 return equals(args[0]);  
  27.             }  
  28.             if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {  
  29.                 //如果目标对象没有实现Object类的基本方法:hashCode  
  30.                 // The target does not implement the hashCode() method itself.  
  31.                 return hashCode();  
  32.             }  
  33.             if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&  
  34.                     method.getDeclaringClass().isAssignableFrom(Advised.class)) {  
  35.                 //根据代理对象的配置来调用服务  
  36.                 // Service invocations on ProxyConfig with the proxy config...  
  37.                 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);  
  38.             }  
  39.   
  40.             Object retVal;  
  41.   
  42.             if (this.advised.exposeProxy) {  
  43.                 // Make invocation available if necessary.  
  44.                 oldProxy = AopContext.setCurrentProxy(proxy);  
  45.                 setProxyContext = true;  
  46.             }  
  47.               
  48.             //得到目标对象的地方  
  49.             // May be null. Get as late as possible to minimize the time we "own" the target,  
  50.             // in case it comes from a pool.  
  51.             target = targetSource.getTarget();  
  52.             if (target != null) {  
  53.                 targetClass = target.getClass();  
  54.             }  
  55.   
  56.             //这里获得定要好的拦截器链  
  57.             // Get the interception chain for this method.  
  58.             List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);  
  59.   
  60.             //如果没有设置拦截器,那么就直接调用target的对应方法  
  61.             // Check whether we have any advice. If we don't, we can fallback on direct  
  62.             // reflective invocation of the target, and avoid creating a MethodInvocation.  
  63.             if (chain.isEmpty()) {  
  64.                 // We can skip creating a MethodInvocation: just invoke the target directly  
  65.                 // Note that the final invoker must be an InvokerInterceptor so we know it does  
  66.                 // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.  
  67.                 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);  
  68.             }  
  69.             //如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法  
  70.             //通过构建一个ReflectiveMethodInvocation来实现  
  71.             else {  
  72.                 // We need to create a method invocation...  
  73.                 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);  
  74.                 // Proceed to the joinpoint through the interceptor chain.  
  75.                 retVal = invocation.proceed();  
  76.             }  
  77.   
  78.             // Massage return value if necessary.  
  79.             if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&  
  80.                     !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {  
  81.                 // Special case: it returned "this" and the return type of the method  
  82.                 // is type-compatible. Note that we can't help if the target sets  
  83.                 // a reference to itself in another returned object.  
  84.                 retVal = proxy;  
  85.             }  
  86.             return retVal;  
  87.         }  
  88.         finally {  
  89.             if (target != null && !targetSource.isStatic()) {  
  90.                 // Must have come from TargetSource.  
  91.                 targetSource.releaseTarget(target);  
  92.             }  
  93.             if (setProxyContext) {  
  94.                 // Restore old proxy.  
  95.                 AopContext.setCurrentProxy(oldProxy);  
  96.             }  
  97.         }  
  98.     }  
  99.       
  100.       
  101. Cglib2AopProxy的intercept拦截:  
  102. final class Cglib2AopProxy implements AopProxy, Serializable:  
  103. (private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable :)  
  104.         public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  
  105.             Object oldProxy = null;  
  106.             boolean setProxyContext = false;  
  107.             Class targetClass = null;  
  108.             Object target = null;  
  109.             try {  
  110.                 if (this.advised.exposeProxy) {  
  111.                     // Make invocation available if necessary.  
  112.                     oldProxy = AopContext.setCurrentProxy(proxy);  
  113.                     setProxyContext = true;  
  114.                 }  
  115.                 // May be <code>null</code>. Get as late as possible to minimize the time we  
  116.                 // "own" the target, in case it comes from a pool.  
  117.                 target = getTarget();  
  118.                 if (target != null) {  
  119.                     targetClass = target.getClass();  
  120.                 }  
  121.                 //从advised中取得配置好的AOP通知  
  122.                 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);  
  123.                 Object retVal;  
  124.                 //如果没有AOP通知配置,那么直接调用target对象的调用方法  
  125.                 // Check whether we only have one InvokerInterceptor: that is,  
  126.                 // no real advice, but just reflective invocation of the target.  
  127.                 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {  
  128.                     // We can skip creating a MethodInvocation: just invoke the target directly.  
  129.                     // Note that the final invoker must be an InvokerInterceptor, so we know  
  130.                     // it does nothing but a reflective operation on the target, and no hot  
  131.                     // swapping or fancy proxying.  
  132.                     retVal = methodProxy.invoke(target, args);  
  133.                 }  
  134.                 else {  
  135.                     //通过CglibMethodInvocation来启动advice通知  
  136.                     // We need to create a method invocation...  
  137.                     retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();  
  138.                 }  
  139.                 retVal = massageReturnTypeIfNecessary(proxy, target, method, retVal);  
  140.                 return retVal;  
  141.             }  
  142.             finally {  
  143.                 if (target != null) {  
  144.                     releaseTarget(target);  
  145.                 }  
  146.                 if (setProxyContext) {  
  147.                     // Restore old proxy.  
  148.                     AopContext.setCurrentProxy(oldProxy);  
  149.                 }  
  150.             }  
  151.         }  
  152.       
  153.       
  154. 目标对象方法的调用:  
  155. 如果没有设置拦截器,那么会对目标对象的方法直接调用。对JDK方式的代理对象,是通过AopUtils.invokeJoinpointUsingReflection(target, method, args)方法实现的。  
  156.   
  157.   
  158.     /** 
  159.      * Invoke the given target via reflection, as part of an AOP method invocation. 
  160.      * @param target the target object 
  161.      * @param method the method to invoke 
  162.      * @param args the arguments for the method 
  163.      * @return the invocation result, if any 
  164.      * @throws Throwable if thrown by the target method 
  165.      * @throws org.springframework.aop.AopInvocationException in case of a reflection error 
  166.      */  
  167.     public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)  
  168.             throws Throwable {  
  169.           
  170.         //这里是使用反射调用target对象方法的地方  
  171.         // Use reflection to invoke the method.  
  172.         try {  
  173.             ReflectionUtils.makeAccessible(method);  
  174.             return method.invoke(target, args);  
  175.         }  
  176.         catch (InvocationTargetException ex) {  
  177.             // Invoked method threw a checked exception.  
  178.             // We must rethrow it. The client won't see the interceptor.  
  179.             throw ex.getTargetException();  
  180.         }  
  181.         catch (IllegalArgumentException ex) {  
  182.             throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +  
  183.                     method + "] on target [" + target + "]", ex);  
  184.         }  
  185.         catch (IllegalAccessException ex) {  
  186.             throw new AopInvocationException("Could not access method [" + method + "]", ex);  
  187.         }  
  188.     }     
  189.       
  190.       
  191. AOP拦截器链的调用:   
  192. 最终AOP的拦截的处理最终都在:org.springframework.aop.framework.ReflectiveMethodInvocation--proceed()  
  193. //在运行拦截器的拦截方法之前,需要对代理方法完成一个匹配判断,通过这个匹配判断来决定拦截器是否满足切面增强的要求。  
  194.     public Object proceed() throws Throwable {  
  195.         //从索引为-1的拦截器开始调用,并按顺序递增  
  196.         //如果拦截器链中的拦截器迭代调用完毕,这里开始调用target的函数,这个函数是通过  
  197.         //反射机制完成的,具体实现在AopUtils.invokeJoinpointUsingReflection方法中  
  198.         //  We start with an index of -1 and increment early.  
  199.         if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {  
  200.             return invokeJoinpoint();  
  201.         }  
  202.   
  203.         Object interceptorOrInterceptionAdvice =  
  204.             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);  
  205.         if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {  
  206.             //这里对拦截器进行动态匹配判断,这里是触发进行匹配的地方,如果和定义的Pointcut匹配,  
  207.             //那么这个advice将会得到执行  
  208.             // Evaluate dynamic method matcher here: static part will already have  
  209.             // been evaluated and found to match.  
  210.             InterceptorAndDynamicMethodMatcher dm =  
  211.                 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;  
  212.             //增强判断      
  213.             if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {  
  214.                 return dm.interceptor.invoke(this);  
  215.             }  
  216.             else {  
  217.                 //如果不匹配,那么process会被递归调用,知道所有的拦截器都被运行过为止  
  218.                 // Dynamic matching failed.  
  219.                 // Skip this interceptor and invoke the next in the chain.  
  220.                 return proceed();  
  221.             }  
  222.         }  
  223.         else {  
  224.             //如果是一个interceptor,直接调用这个interceptor对应的方法  
  225.             // It's an interceptor, so we just invoke it: The pointcut will have  
  226.             // been evaluated statically before this object was constructed.  
  227.             return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);  
  228.         }  
  229.     }  
  230.   
  231.   
  232. 配置通知器:  
  233. 在整个AopProxy代理对象的回调过程中,先回到ReflectiveMethodInvocation的proceed方法。方法中有一句  
  234. Object interceptorOrInterceptionAdvice =  
  235.             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);  
  236. interceptorOrInterceptionAdvice是获得的拦截器,他通过拦截器机制对目标对象的行为增强器作用。  
  237. 这个值可以先看JdkDynamicAopProxy的invoke中  
  238. // Get the interception chain for this method.  
  239. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);             
  240. 知道到实现:  
  241. AdvisedSupport  
  242. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {  
  243. //这里使用了methodCache,一个map的cache,如果没有初始化过,会通过DefaultAdvisorChainFactory完成  
  244.     MethodCacheKey cacheKey = new MethodCacheKey(method);  
  245.     List<Object> cached = this.methodCache.get(cacheKey);  
  246.     if (cached == null) {  
  247.         cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(  
  248.                 this, method, targetClass);  
  249.         this.methodCache.put(cacheKey, cached);  
  250.     }  
  251.     return cached;  
  252. }  
  253. 取得拦截器链的工作是由配置好的advisorChainFactory来完成的,他是一个通知器连的工厂。  
  254. 在DefaultAdvisorChainFactory实现了对通知链的获取过程,具体实现可查看源码。  
  255.   
  256. 在ProxyFactoryBean的getObject方法中对advisor进行初始化时,从XML配置中获取了advisor通知器。  
  257.   
  258. Object advice;  
  259. //判断是单例还是prototype  
  260. if (this.singleton || this.beanFactory.isSingleton(name)) {  
  261.     //这里是取得advice的地方,是通个beanFactory取得的,把interceptor的名字交给BeanFactory,然后通过调用getBean去获取。  
  262.     advice = this.beanFactory.getBean(name);  
  263. }  
  264. else {  
  265.     // It's a prototype Advice or Advisor: replace with a prototype.  
  266.     // Avoid unnecessary creation of prototype bean just for advisor chain initialization.  
  267.     advice = new PrototypePlaceholderAdvisor(name);  
  268. }  
  269. addAdvisorOnChainCreation(advice, name);  
  270.   
  271. advisor通知器的取得是委托给IoC容器完成的。  
  272. DefaultListableBeanFactory的子类AbstractAutowireCapableBeanFactory的initializeBean初始化方法,判断了bean是否继承了BeanFactoryAware,如果是则设置回调。  
  273.   
  274.   
  275. Advice通知的实现:  
  276. 后续  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring技术内幕 深入解析Spring架构与设计原理1(完整清晰版),一共两部分,这是第一部分 《Spring技术内幕:深入解析Spring架构与设计原理》是Spring领域的问鼎之作,由业界拥有10余年开发经验的资深Java专家亲自执笔!Java开发者社区和Spring开发者社区一致强烈推荐。国内第一本基于Spring3.0的著作,从源代码的角度对Spring的内核和各个主要功能模块的架构、设计和实现原理进行了深入剖析。你不仅能从木书中参透Spring框架的优秀架构和设计思想,而且还能从Spring优雅的实现源码中一窥Java语言的精髓。此外,《Spring技术内幕:深入解析Spring架构与设计原理》还展示了阅读源代码的卓越方法,不仅授你以鱼,而且还授你以渔!   如果你以一种淡定的心态翻开这本书,无论你是Java程序员、Spring开发者,还是平台开发人员、系统架构师,抑或是对开源软件源代码着迷的代码狂人,都能从《Spring技术内幕:深入解析Spring架构与设计原理》中受益。   《Spring技术内幕:深入解析Spring架构与设计原理》特色:   作者从业10余载,悟透Spring等开源软件的本质,权威性毋庸置疑。   Java开发者社区、专业Spring开发者社区和架构师社区一致鼎力推荐!   深入解析Spring架构原理与设计思想,探究Spring成功的奥秘。   揭开Spring源代码的神秘面纱,展示系统阅读开源软件源代码的方法和秘诀。   如果你正在思考下面这些问题,也许《Spring技术内幕:深入解析Spring架构与设计原理》就是你想要的!   掌握Spring的架构原理与设计思想真的能让开发者如虎添翼吗?   IoC容器如何掌控以POJO为基础的Bean对象?它的轻量级开发设计思想是如何实现的?   Spring产品级的IoC容器是如何作为一个完整的系统实现并运行的?它如何启动?如何完成Bean的解析和载入?又如何实现Bean的生命周期管理?   Spring如何简捷地在JVM上实现AOP功能?   Spring AOP如何实现Aspect编织功能?   Spring如何实现各种数据库操作组件的集成?   Spring如何在Web环境中集成IoC容器并为Web应用开发提供利器?   我们耳熟能详的MVC模式在Spring中是如何实现的?   Spring MVC如何灵活地集成各种丰富的视图展现方案?   Spring实现远端调用的方案有很多种,你知道它们之间的优劣差异吗?   Spring ACEGI安全框架在用户验证和授权机制的实现上有何过人之处?   如何在Spring的基础上进行扩展开发?   你是否曾经也有过分析开源软件源代码的冲动?你想掌握分析源代码的最佳实践吗?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值