Spring AOP网上例子整理(三)

     作者: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工厂的方法,能找到上述第二行其实是调用了如下这个方法。

 

  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。下面注意,在这面这一行的时候,我们已经获取到了实例。

  1. Object sharedInstance = getSingleton(beanName);  
Object sharedInstance = getSingleton(beanName);

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

 

 

  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方法。

 

  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方法。

 

 

  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方法来看一下。

 

  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();
		}
	}

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

  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方法,这是用来获取单例实例的,而真正的加强也是在这里发生的,我们来看一下。

 

  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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我们来实现一个简单的 Spring AOP例子,假设我们有一个计算器类 Calculator,它有两个方法 add 和 subtract,我们想要在这两个方法执行前后打印日志。 首先,我们需要定义一个切面类 LogAspect,它包含两个方法,一个执行前的方法 before,一个执行后的方法 after。 ```java @Aspect @Component public class LogAspect { @Before("execution(* com.example.demo.Calculator.*(..))") public void before(JoinPoint joinPoint) { System.out.println("before " + joinPoint.getSignature().getName()); } @After("execution(* com.example.demo.Calculator.*(..))") public void after(JoinPoint joinPoint) { System.out.println("after " + joinPoint.getSignature().getName()); } } ``` 我们使用 @Aspect 注解将这个类标记为切面类,使用 @Before 和 @After 注解分别标记 before 和 after 方法,它们的参数是一个切入点表达式,表示在哪些方法执行前或执行后应该执行这个方法。这里我们使用了 execution(* com.example.demo.Calculator.*(..)) 表达式,它表示在 Calculator 类中的所有方法执行前或执行后都要执行这个方法。 接下来,我们需要在 Spring 的配置文件中声明这个切面类,并开启 AOP 功能。假设我们的配置文件名为 application-context.xml,内容如下: ```xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <bean id="calculator" class="com.example.demo.Calculator"/> <bean id="logAspect" class="com.example.demo.LogAspect"/> <aop:aspectj-autoproxy/> </beans> ``` 我们使用 <bean> 标签声明一个 Calculator 类的实例,并使用 <bean> 标签声明一个 LogAspect 类的实例。然后使用 <aop:aspectj-autoproxy> 标签开启 AOP 功能。这里需要注意,我们使用了 AspectJ 注解来声明切面类和切入点表达式,所以需要使用 <aop:aspectj-autoproxy> 标签来开启 AspectJ 支持。 最后,我们在程序中使用 Spring 的实例工厂来获取 Calculator 类的实例,并使用它的 add 和 subtract 方法进行测试。 ```java public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml"); Calculator calculator = (Calculator) context.getBean("calculator"); calculator.add(1, 2); calculator.subtract(2, 1); } } ``` 运行程序,我们应该可以看到如下的输出: ``` before add after add before subtract after subtract ``` 这表示我们的切面类 LogAspect 成功地拦截了 Calculator 类中的 add 和 subtract 方法的执行,并在它们执行前后打印了日志。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值