现在的位置: 首页 > 综合 > 正文

spring源码学习之路—深入AOP(终)

2017年12月12日 ⁄ 综合 ⁄ 共 12624字 ⁄ 字号 评论关闭

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

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

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

public interface FactoryBean<T> {

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

                 getObject这个方法,就是用来获取被这个factorybean加强后的对象的,上一章测试的过程中,最终就是调用了这个方法,来完成了对bean的加强。我们来跟踪一下上一次测试的代码,看看到底是在什么地方调用的。这里再次贴出来上次测试的代码,方便解释。

public class TestAOP {

	public static void main(String[] args) {
		ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:beans.xml");
		TestTarget target = (TestTarget) applicationContext.getBean("testAOP");
		target.test();
		System.out.println("------无敌分割线-----");
		target.test2();
	}
	
}

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

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

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

Object sharedInstance = getSingleton(beanName);

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

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

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

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

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

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

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

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

抱歉!评论已关闭.