Spring AOP网上例子整理(三)

来源:互联网 发布:jdbc 连接mysql 编辑:程序博客网 时间:2024/06/09 19:37

     作者:zuoxiaolong8810(左潇龙),转载请注明出处。

                上一章和各位一起看了一下springAOP的工作流程,当我们给出AOP相关的配置以后,直接从IOC容器中拿出来的就是已经加强过的bean。这说明spring在这个过程中一定做了什么。

                本章我们就一起来看一下spring是如何完成对bean的增强的,首先我们来看一下,FactoryBean接口中一个方法的定义。

01.public interface FactoryBean<T> {  02.  03.    /** 04.     * Return an instance (possibly shared or independent) of the object 05.     * managed by this factory. 06.     * <p>As with a {@link BeanFactory}, this allows support for both the 07.     * Singleton and Prototype design pattern. 08.     * <p>If this FactoryBean is not fully initialized yet at the time of 09.     * the call (for example because it is involved in a circular reference), 10.     * throw a corresponding {@link FactoryBeanNotInitializedException}. 11.     * <p>As of Spring 2.0, FactoryBeans are allowed to return <code>null</code> 12.     * objects. The factory will consider this as normal value to be used; it 13.     * will not throw a FactoryBeanNotInitializedException in this case anymore. 14.     * FactoryBean implementations are encouraged to throw 15.     * FactoryBeanNotInitializedException themselves now, as appropriate. 16.     * @return an instance of the bean (can be <code>null</code>) 17.     * @throws Exception in case of creation errors 18.     * @see FactoryBeanNotInitializedException 19.     */  20.    T getObject() throws Exception;  

  

其实整个过程也就两行代码,第一行代码,是我们对IOC容器的初始化,这时其实并没有发生对bean的增强,原因就是这个时候只是完成了对ProxyFactoryBean的初始化,也就是相当于我们已经new出来了一个ProxyFactoryBean,但是此时并没有调用接口方法,去获得加强后的bean。

 

               下面我们去跟进第二行获取testAOP的代码,来看一下究竟。首先我们会找到AbstractApplicationContext中的getBean方法,但是这个类并不负责bean的实例化工作,而是交给了bean工厂,我们跟踪bean工厂的方法,能找到上述第二行其实是调用了如下这个方法。

 

[java] view plaincopyprint?
  1. @SuppressWarnings("unchecked")  
  2.     protected <T> T doGetBean(  
  3.             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  
  4.             throws BeansException {  
  5.   
  6.         final String beanName = transformedBeanName(name);  
  7.         Object bean;  
  8.   
  9.         // Eagerly check singleton cache for manually registered singletons.   
  10.         Object sharedInstance = getSingleton(beanName);  
  11.         if (sharedInstance != null && args == null) {  
  12.             if (logger.isDebugEnabled()) {  
  13.                 if (isSingletonCurrentlyInCreation(beanName)) {  
  14.                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +  
  15.                             "' that is not fully initialized yet - a consequence of a circular reference");  
  16.                 }  
  17.                 else {  
  18.                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");  
  19.                 }  
  20.             }  
  21.             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
  22.         }  
  23.   
  24.         else {  
  25.             // Fail if we're already creating this bean instance:   
  26.             // We're assumably within a circular reference.   
  27.             if (isPrototypeCurrentlyInCreation(beanName)) {  
  28.                 throw new BeanCurrentlyInCreationException(beanName);  
  29.             }  
  30.   
  31.             // Check if bean definition exists in this factory.   
  32.             BeanFactory parentBeanFactory = getParentBeanFactory();  
  33.             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
  34.                 // Not found -> check parent.   
  35.                 String nameToLookup = originalBeanName(name);  
  36.                 if (args != null) {  
  37.                     // Delegation to parent with explicit args.   
  38.                     return (T) parentBeanFactory.getBean(nameToLookup, args);  
  39.                 }  
  40.                 else {  
  41.                     // No args -> delegate to standard getBean method.   
  42.                     return parentBeanFactory.getBean(nameToLookup, requiredType);  
  43.                 }  
  44.             }  
  45.   
  46.             if (!typeCheckOnly) {  
  47.                 markBeanAsCreated(beanName);  
  48.             }  
  49.   
  50.             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
  51.             checkMergedBeanDefinition(mbd, beanName, args);  
  52.   
  53.             // Guarantee initialization of beans that the current bean depends on.   
  54.             String[] dependsOn = mbd.getDependsOn();  
  55.             if (dependsOn != null) {  
  56.                 for (String dependsOnBean : dependsOn) {  
  57.                     getBean(dependsOnBean);  
  58.                     registerDependentBean(dependsOnBean, beanName);  
  59.                 }  
  60.             }  
  61.   
  62.             // Create bean instance.   
  63.             if (mbd.isSingleton()) {  
  64.                 sharedInstance = getSingleton(beanName, new ObjectFactory() {  
  65.                     public Object getObject() throws BeansException {  
  66.                         try {  
  67.                             return createBean(beanName, mbd, args);  
  68.                         }  
  69.                         catch (BeansException ex) {  
  70.                             // Explicitly remove instance from singleton cache: It might have been put there   
  71.                             // eagerly by the creation process, to allow for circular reference resolution.   
  72.                             // Also remove any beans that received a temporary reference to the bean.   
  73.                             destroySingleton(beanName);  
  74.                             throw ex;  
  75.                         }  
  76.                     }  
  77.                 });  
  78.                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
  79.             }  
  80.   
  81.             else if (mbd.isPrototype()) {  
  82.                 // It's a prototype -> create a new instance.   
  83.                 Object prototypeInstance = null;  
  84.                 try {  
  85.                     beforePrototypeCreation(beanName);  
  86.                     prototypeInstance = createBean(beanName, mbd, args);  
  87.                 }  
  88.                 finally {  
  89.                     afterPrototypeCreation(beanName);  
  90.                 }  
  91.                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
  92.             }  
  93.   
  94.             else {  
  95.                 String scopeName = mbd.getScope();  
  96.                 final Scope scope = this.scopes.get(scopeName);  
  97.                 if (scope == null) {  
  98.                     throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");  
  99.                 }  
  100.                 try {  
  101.                     Object scopedInstance = scope.get(beanName, new ObjectFactory() {  
  102.                         public Object getObject() throws BeansException {  
  103.                             beforePrototypeCreation(beanName);  
  104.                             try {  
  105.                                 return createBean(beanName, mbd, args);  
  106.                             }  
  107.                             finally {  
  108.                                 afterPrototypeCreation(beanName);  
  109.                             }  
  110.                         }  
  111.                     });  
  112.                     bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  
  113.                 }  
  114.                 catch (IllegalStateException ex) {  
  115.                     throw new BeanCreationException(beanName,  
  116.                             "Scope '" + scopeName + "' is not active for the current thread; " +  
  117.                             "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",  
  118.                             ex);  
  119.                 }  
  120.             }  
  121.         }  
  122.   
  123.         // Check if required type matches the type of the actual bean instance.   
  124.         if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {  
  125.             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  
  126.         }  
  127.         return (T) bean;  
  128.     }  
@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'");}}bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dependsOnBean : dependsOn) {getBean(dependsOnBean);registerDependentBean(dependsOnBean, beanName);}}// Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, new ObjectFactory() {public Object getObject() throws BeansException {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, new ObjectFactory() {public Object getObject() throws BeansException {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; " +"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}// Check if required type matches the type of the actual bean instance.if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return (T) bean;}

这是一个重载方法,后面三个参数两个为null,一个为false。下面注意,在这面这一行的时候,我们已经获取到了实例。

[java] view plaincopyprint?
  1. Object sharedInstance = getSingleton(beanName);  
Object sharedInstance = getSingleton(beanName);

            所以分支在碰到第一个if判断时,会直接进入if块而不是else块,在这里提醒一下,这个是获取的单例的bean实例,而这个sharedInstance并不是TestTarget,而是ProxyFactoryBean的实例。好了,接下来相信你已经明白了,我们该进入getObjectForBeanInstance这个方法了,来看这个方法。

 

 

[java] view plaincopyprint?
  1. protected Object getObjectForBeanInstance(  
  2.         Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
  3.   
  4.     // Don't let calling code try to dereference the factory if the bean isn't a factory.   
  5.     if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  
  6.         throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  
  7.     }  
  8.   
  9.     // Now we have the bean instance, which may be a normal bean or a FactoryBean.   
  10.     // If it's a FactoryBean, we use it to create a bean instance, unless the   
  11.     // caller actually wants a reference to the factory.   
  12.     if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
  13.         return beanInstance;  
  14.     }  
  15.   
  16.     Object object = null;  
  17.     if (mbd == null) {  
  18.         object = getCachedObjectForFactoryBean(beanName);  
  19.     }  
  20.     if (object == null) {  
  21.         // Return bean instance from factory.   
  22.         FactoryBean factory = (FactoryBean) beanInstance;  
  23.         // Caches object obtained from FactoryBean if it is a singleton.   
  24.         if (mbd == null && containsBeanDefinition(beanName)) {  
  25.             mbd = getMergedLocalBeanDefinition(beanName);  
  26.         }  
  27.         boolean synthetic = (mbd != null && mbd.isSynthetic());  
  28.         object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
  29.     }  
  30.     return object;  
  31. }  
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}Object object = null;if (mbd == null) {object = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.FactoryBean factory = (FactoryBean) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);}boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}

方法的刚开始是两个卫语句,第一个判断如果是想获得factorybean本身,却又不是factorybean则抛出异常,第二个则是正常的获得factorybean。但是我们都不属于这两种情况。所以在经过getCachedObjectForFactoryBean获取无果和getCachedObjectForFactoryBean获取到bean定义以后,就进入了getObjectFromFactoryBean方法。

 

[java] view plaincopyprint?
  1. protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {  
  2.         if (factory.isSingleton() && containsSingleton(beanName)) {  
  3.             synchronized (getSingletonMutex()) {  
  4.                 Object object = this.factoryBeanObjectCache.get(beanName);  
  5.                 if (object == null) {  
  6.                     object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
  7.                     this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));  
  8.                 }  
  9.                 return (object != NULL_OBJECT ? object : null);  
  10.             }  
  11.         }  
  12.         else {  
  13.             return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
  14.         }  
  15.     }  
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {if (factory.isSingleton() && containsSingleton(beanName)) {synchronized (getSingletonMutex()) {Object object = this.factoryBeanObjectCache.get(beanName);if (object == null) {object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));}return (object != NULL_OBJECT ? object : null);}}else {return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);}}

进入以后,由于proxyFactorybean是单例bean,所以会进入到if块不是else块,接下来系统再次尝试从cache中获得,自然是无果。接下来依然会进入到和else一样的方法doGetObjectFromFactoryBean,先不说这个方法,看后面,获得以后就会放入cache,然后直接将对象返回。所以如果重复调用,下一次就会从cache当中取出来直接返回。好了,接下来我们进去doGetObjectFromFactoryBean方法。

 

 

[java] view plaincopyprint?
  1. private Object doGetObjectFromFactoryBean(  
  2.         final FactoryBean factory, final String beanName, final boolean shouldPostProcess)  
  3.         throws BeanCreationException {  
  4.   
  5.     Object object;  
  6.     try {  
  7.         if (System.getSecurityManager() != null) {  
  8.             AccessControlContext acc = getAccessControlContext();  
  9.             try {  
  10.                 object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
  11.                     public Object run() throws Exception {  
  12.                             return factory.getObject();  
  13.                         }  
  14.                     }, acc);  
  15.             }  
  16.             catch (PrivilegedActionException pae) {  
  17.                 throw pae.getException();  
  18.             }  
  19.         }  
  20.         else {  
  21.             object = factory.getObject();  
  22.         }  
  23.     }  
  24.     catch (FactoryBeanNotInitializedException ex) {  
  25.         throw new BeanCurrentlyInCreationException(beanName, ex.toString());  
  26.     }  
  27.     catch (Throwable ex) {  
  28.         throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);  
  29.     }  
  30.   
  31.       
  32.     // Do not accept a null value for a FactoryBean that's not fully   
  33.     // initialized yet: Many FactoryBeans just return null then.   
  34.     if (object == null && isSingletonCurrentlyInCreation(beanName)) {  
  35.         throw new BeanCurrentlyInCreationException(  
  36.                 beanName, "FactoryBean which is currently in creation returned null from getObject");  
  37.     }  
  38.   
  39.     if (object != null && shouldPostProcess) {  
  40.         try {  
  41.             object = postProcessObjectFromFactoryBean(object, beanName);  
  42.         }  
  43.         catch (Throwable ex) {  
  44.             throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);  
  45.         }  
  46.     }  
  47.   
  48.     return object;  
  49. }  
private Object doGetObjectFromFactoryBean(final FactoryBean factory, final String beanName, final boolean shouldPostProcess)throws BeanCreationException {Object object;try {if (System.getSecurityManager() != null) {AccessControlContext acc = getAccessControlContext();try {object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {public Object run() throws Exception {return factory.getObject();}}, acc);}catch (PrivilegedActionException pae) {throw pae.getException();}}else {object = factory.getObject();}}catch (FactoryBeanNotInitializedException ex) {throw new BeanCurrentlyInCreationException(beanName, ex.toString());}catch (Throwable ex) {throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);}// Do not accept a null value for a FactoryBean that's not fully// initialized yet: Many FactoryBeans just return null then.if (object == null && isSingletonCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");}if (object != null && shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);}}return object;}

此处判断了一下当前是否设置了安全管理器,我们并没有设置,所以将直接调用ProxyFactoryBean的getObject方法,也就是对bean增强的地方。下面我们着重来看一下是如何对bean进行增强的。首先我们进入到ProxyFactoryBean的getObject方法来看一下。

 

[java] view plaincopyprint?
  1. public Object getObject() throws BeansException {  
  2.         initializeAdvisorChain();  
  3.         if (isSingleton()) {  
  4.             return getSingletonInstance();  
  5.         }  
  6.         else {  
  7.             if (this.targetName == null) {  
  8.                 logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +  
  9.                         "Enable prototype proxies by setting the 'targetName' property.");  
  10.             }  
  11.             return newPrototypeInstance();  
  12.         }  
  13.     }  
public Object getObject() throws BeansException {initializeAdvisorChain();if (isSingleton()) {return getSingletonInstance();}else {if (this.targetName == null) {logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +"Enable prototype proxies by setting the 'targetName' property.");}return newPrototypeInstance();}}

此处主要是先初始化了一下通知器链,然后就会根据是否单例做相应的动作,我们看一下初始化通知器链的进行。

[java] view plaincopyprint?
  1. private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {  
  2.         if (this.advisorChainInitialized) {  
  3.             return;  
  4.         }  
  5.   
  6.         if (!ObjectUtils.isEmpty(this.interceptorNames)) {  
  7.             if (this.beanFactory == null) {  
  8.                 throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +  
  9.                         "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));  
  10.             }  
  11.   
  12.             // Globals can't be last unless we specified a targetSource using the property...   
  13.             if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&  
  14.                     this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {  
  15.                 throw new AopConfigException("Target required after globals");  
  16.             }  
  17.   
  18.             // Materialize interceptor chain from bean names.   
  19.             for (String name : this.interceptorNames) {  
  20.                 if (logger.isTraceEnabled()) {  
  21.                     logger.trace("Configuring advisor or advice '" + name + "'");  
  22.                 }  
  23.   
  24.                 if (name.endsWith(GLOBAL_SUFFIX)) {  
  25.                     if (!(this.beanFactory instanceof ListableBeanFactory)) {  
  26.                         throw new AopConfigException(  
  27.                                 "Can only use global advisors or interceptors with a ListableBeanFactory");  
  28.                     }  
  29.                     addGlobalAdvisor((ListableBeanFactory) this.beanFactory,  
  30.                             name.substring(0, name.length() - GLOBAL_SUFFIX.length()));  
  31.                 }  
  32.   
  33.                 else {  
  34.                     // If we get here, we need to add a named interceptor.   
  35.                     // We must check if it's a singleton or prototype.   
  36.                     Object advice;  
  37.                     if (this.singleton || this.beanFactory.isSingleton(name)) {  
  38.                         // Add the real Advisor/Advice to the chain.   
  39.                         advice = this.beanFactory.getBean(name);  
  40.                     }  
  41.                     else {  
  42.                         // It's a prototype Advice or Advisor: replace with a prototype.   
  43.                         // Avoid unnecessary creation of prototype bean just for advisor chain initialization.   
  44.                         advice = new PrototypePlaceholderAdvisor(name);  
  45.                     }  
  46.                     addAdvisorOnChainCreation(advice, name);  
  47.                 }  
  48.             }  
  49.         }  
  50.   
  51.         this.advisorChainInitialized = true;  
  52.     }  
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {if (this.advisorChainInitialized) {return;}if (!ObjectUtils.isEmpty(this.interceptorNames)) {if (this.beanFactory == null) {throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));}// Globals can't be last unless we specified a targetSource using the property...if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {throw new AopConfigException("Target required after globals");}// Materialize interceptor chain from bean names.for (String name : this.interceptorNames) {if (logger.isTraceEnabled()) {logger.trace("Configuring advisor or advice '" + name + "'");}if (name.endsWith(GLOBAL_SUFFIX)) {if (!(this.beanFactory instanceof ListableBeanFactory)) {throw new AopConfigException("Can only use global advisors or interceptors with a ListableBeanFactory");}addGlobalAdvisor((ListableBeanFactory) this.beanFactory,name.substring(0, name.length() - GLOBAL_SUFFIX.length()));}else {// If we get here, we need to add a named interceptor.// We must check if it's a singleton or prototype.Object advice;if (this.singleton || this.beanFactory.isSingleton(name)) {// Add the real Advisor/Advice to the chain.advice = this.beanFactory.getBean(name);}else {// It's a prototype Advice or Advisor: replace with a prototype.// Avoid unnecessary creation of prototype bean just for advisor chain initialization.advice = new PrototypePlaceholderAdvisor(name);}addAdvisorOnChainCreation(advice, name);}}}this.advisorChainInitialized = true;}

可以看到,其中针对我们配置的interpretorNames进行了循环,我们并非是配置的全局通知器,所以会进入else块,然后因为我们配置的testAdvisor默认是单例的,所以会从bean工厂中去获取这个实例,此时TestAdvisor已经实例化完成的,我们只是去取一下而已。然后就会进入addAdvisorOnChainCreation方法。这个方法不再一一贴进来,各位有兴趣的可以自己去看一下,就是把通知器加到了通知链当中。

 

              值得注意的是在这个过程中,触发了一个这样的方法this.advisorAdapterRegistry.wrap(next)。这个方法就是用来包装通知器的,如果不是advisor而是advice,就会包装一下返回。

              好了,接着刚才的过程,初始化通知器链完成以后,就会进入getSingletonInstance方法,这是用来获取单例实例的,而真正的加强也是在这里发生的,我们来看一下。

 

[java] view plaincopyprint?
  1. private synchronized Object getSingletonInstance() {  
  2.     if (this.singletonInstance == null) {  
  3.         this.targetSource = freshTargetSource();  
  4.         if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {  
  5.             // Rely on AOP infrastructure to tell us what interfaces to proxy.   
  6.             Class targetClass = getTargetClass();  
  7.             if (targetClass == null) {  
  8.                 throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");  
  9.             }  
  10.             setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));  
  11.         }  
  12.         // Initialize the shared singleton instance.   
  13.         super.setFrozen(this.freezeProxy);  
  14.         this.singletonInstance = getProxy(createAopProxy());  
  15.     }  
  16.     return this.singletonInstance;  
  17. }  
private synchronized Object getSingletonInstance() {if (this.singletonInstance == null) {this.targetSource = freshTargetSource();if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {// Rely on AOP infrastructure to tell us what interfaces to proxy.Class targetClass = getTargetClass();if (targetClass == null) {throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");}setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}// Initialize the shared singleton instance.super.setFrozen(this.freezeProxy);this.singletonInstance = getProxy(createAopProxy());}return this.singletonInstance;}

此时第一次获取,单例实例为null,所以会进入if块,首先刷新targetSource,因为我们的Target类没有实现targetSource接口,所以会由spring帮我们产生一个targetSource适配,这里是使用的适配器的模式,有兴趣可以进去看一下,我们此处不关注这个。接下来,会去判断代理接口,并且设置代理接口,但是我们的target未实现任何接口,所以此处interfaces仍然为空的,所以最后一步createAopProxy时,会帮我们创建cglib的proxy。最终由cglib生成代理返回。

执行下国际惯例,说完以后总要稍微总结一下,主要说几点:

1.在IOC容器初始化的过程中,并没有发生增强的动作,而是初始化了proxyFactoryBean。

2.如果配置中不指定,所有bean默认都是单例和非延迟加载的,也就是说所有的bean都将在第一次IOC容器初始化时全部实例化,所以上一章中所配置的三个bean都是在IOC容器初始化时进行的实例化。

3.springAOP代理有两种方式,一种是JDK提供的动态代理,一种是cglib字节码生成的技术,当要代理的类有实现的接口的时候,就会针对接口进行代理,否则就会采用cglib直接生成字节码产生子类。

 

              到此处,我们已经基本上完全跟了一遍整个bean增强的过程,也大概了解了springAOP的大概原理,相信各位心中应该有个大概的印象了,其实springAOP增强的原理已经浮现出来了,接下来再研究下去,可能会收获甚微,还是要结合平时的应用和自己的兴趣去体会,始终不赞同一头扎进去就埋头苦干的作风。

              好了,spring源码学习之路就圆满结束了,虽说时间不长,但收获甚大。各位如果有兴趣,相信现在也完全有能力自己去看源码了,以后有问题,不要找度娘了,找源码吧。



0 0