`
eric_hwp
  • 浏览: 125293 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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



分享到:
评论

相关推荐

    Spring 2.0 AOP 完整例子

    网上找了很多例子多数都不能运行。包括after,before,round,throw切入,可对类直接拦截,不需要定义接口文件,自己研究了2天整理出来的。 Spring AOP 的完整例子,可直接运行。带jar包。

    spring知识点代码示例整理

    - `spring_integration_jdbc` 文件夹提供了 Spring 与 JDBC 结合使用的例子。Spring 提供了 JdbcTemplate 和 NamedParameterJdbcTemplate,简化了 SQL 查询和数据访问操作。 6. **Spring 用户模块** - `spring_...

    spring.net 资料整理

    此外,Spring.NET 还支持 AOP(面向切面编程),允许开发者在不修改源代码的情况下,向现有代码添加新的功能或监控行为。AOP 在 Spring.NET 中主要通过代理模式实现,可以用于事务管理、日志记录、性能度量等场景。 ...

    maven整理Spring+mybatis多对多多对一例子

    在我们的例子中,我们需要在pom.xml中添加Spring、MyBatis以及相关库的依赖。 接下来,Spring框架是Java领域的一个全功能容器,用于处理对象的依赖注入、AOP(面向切面编程)、事务管理等。在多对多和多对一的关系...

    java-用Java动态代理实现AOP.pdf

    9. 其他AOP框架:文档提及除了Spring AOP以外,还有JAC(Java Aspect Components)和Jboss AOP等其他AOP框架,这些都是Java生态中实现AOP的工具。 通过这些知识点,可以看出文档主要围绕Java动态代理的原理及其在...

    spring-boot示例项目

    Spring Boot为Spring平台及第三方库提供开箱即用的设置,这样你就可以有条不紊地开始。多数Spring Boot应用只需要很少的Spring配置。 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Sprin

    spring roo使用文档

    ### Spring Roo 使用文档知识点概述 #### 一、Spring Roo ...以上是根据给定的 Spring Roo 文档摘要整理出的关键知识点,通过这些知识点的学习和掌握,可以帮助开发者更高效地使用 Spring Roo 构建高质量的应用程序。

    Spring MVC简介_动力节点Java学院整理

    项目创建完成后,我们需要在WEB-INF目录下创建一个名为lib的文件夹,然后将所需的Spring相关jar包(如spring-aop、spring-beans、spring-context、spring-core、spring-expression、spring-web、spring-webmvc以及...

    2024最新java-SSHM面试题整理.zip

    - 解释Spring的IoC和AOP概念并给出实际应用例子 - 描述一个完整的Struts 2请求处理流程 - Hibernate的懒加载和立即加载的区别,以及如何配置 - MyBatis是如何通过XML或注解实现动态SQL的 - SSHM整合中,如何...

    struts2.1.6+spring2.0+hibernate3.2常用配置包

    另外三大框架的添加顺序也需要注意下,我的添加顺序是 struts2.1.6、spring2.0、hibernate3.2 spring版本差异(包方面)没有研究过,大致雷同,也应该保持版本一致,即在同一个稳定发行包中下载的包。 以下包后面跟...

    SSM框架整合crm小例子(源码+资料+数据库+页面+笔记等)

    SSM框架,全称Spring MVC + Spring + Mybatis,是Java Web开发中广泛采用的三大开源框架集成。这个"SSM框架整合crm小例子"是一个适合初学者的实践项目,涵盖了从开发环境搭建到功能实现的全过程。让我们深入探讨一下...

    hibernate例子程序SSH.part01.rar

    【标题】"hibernate例子程序SSH.part01.rar"是一个关于Hibernate框架的示例程序,结合了Spring、Struts和Hibernate(SSH)这三大Java Web开发中的主流框架。这个压缩包是尚学堂提供的,尚学堂是一家知名的IT教育机构...

    struts2个人整理文档

    1. `applicationContext.xml`:Spring的配置文件,用于定义bean、事务管理和AOP(面向切面编程)等。在实际应用中,你需要根据项目需求来定制这个文件,例如配置数据源、SessionFactory、事务管理规则等。 2. ...

    大数据进阶文档

    Spring是一个强大的框架,提供依赖注入、AOP(面向切面编程)等功能,而MyBatis则是一个轻量级的持久层框架,专注于SQL映射和数据库交互。将两者整合可以实现高效、灵活的数据访问和业务逻辑处理。 首先,Spring...

    SSHLogin实例(下载)[整理].pdf

    【SSHLogin实例(下载)[整理].pdf】文档主要介绍了MVC设计模式以及SSH(Struts+Spring+Hibernate)框架在Web应用中的使用,包括各组件的功能、优缺点以及一个简单的SSH登录实例。 **MVC模式** MVC模式是一种常见的...

    java面试资料整理.zip

    14. **Spring框架**:熟悉Spring的核心概念,如依赖注入(DI)和面向切面编程(AOP),以及Spring Boot和Spring MVC的使用。 15. **数据库操作**:掌握SQL语言,了解JDBC的使用,以及ORM框架如Hibernate和MyBatis的...

    张孝祥正在整理Java就业面试题大全

    1. Spring框架:依赖注入、AOP、事务管理、Spring Boot等核心概念。 2. MyBatis:SQL映射、动态SQL、缓存机制,以及MyBatis-Spring的整合。 3. 数据库:SQL优化、索引原理、事务与锁机制,以及NoSQL数据库的使用。 4...

    WebAppTest:基于Spring MVC并配置Maven的Web应用

    3. **面向切面编程(AOP)**:Spring框架提供了AOP支持,可以方便地实现如日志记录、事务管理等跨切面的功能。 4. **强大的数据绑定**:Spring MVC自动处理HTTP请求和响应,支持数据验证和类型转换。 **Maven** ...

    《IT学习资料2》-Java学习过程中笔记的配套代码.zip

    6. **笔记与教学材料**(notes):这里可能是作者在学习过程中整理的笔记,可能涵盖了各个知识点的解析、例子和问题解答,是很好的学习参考资料。 7. **Spring Batch**:这是一个强大的批处理框架,用于执行大规模...

    Java Web开发实战1200例(第2卷) 电子书 可复制

    本书提供的三种电子书格式——.azw3、.epub和.mobi,满足了不同设备和阅读软件的需求,让读者无论在电脑、手机还是平板上都能便捷阅读,并且特别强调的是,内容可直接复制,这对于学习过程中查阅和笔记整理非常方便...

Global site tag (gtag.js) - Google Analytics