Spring源码分析(四)(AOP实现)(1)

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37598011/article/details/89971937

    在Spring AOP实现中,使用的核心技术是动态代理。通过动态代理特性可以为任意Java对象创建代理对象。在Spring中可以具体分为JDK代理和CGLIB代理。

    在Spring AOP中有一个核心类这个类就是ProxyFactoryBean,这个类是在Spring Ioc环境中创建AOP应用的底层方法,Spring通过这个类完成了对AOP使用的封装。

建立AopProxy代理对象

    在 ProxyFactoryBean中,通过 interceptorNames属性来配置已经定义好的通知器 Advisor。在ProxyFactoryBean中,需要为 target目标对象生成 Proxy代理对象,从而为AOP横切面的编织做好准备工作。
    ProxyFactoryBean的AOP实现需要依赖JDK或者CGLIB提供的Proxy特性。从FactoryBean中获取对象,是以 getObject()方法作为入口完成的。对ProxyFactoryBean而言,把需要对 target目标对象增加的增强处理,都通过 getObject()方法进行封装了,这些增强处理是为AOP功能的实现提供服务的。 getObject()的实现如下:

	public Object getObject() throws BeansException {
		//初始化通知器链
		initializeAdvisorChain();
		//对singleton和prototype类型做区分,生成对应的proxy
		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();
		}
	}

    getObject()方法首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备。在生成代理对象时,因为 Spring中有 singleton类型和 prototype类型这两种不同的Bean,所以要对代理对象的生成做一个区分。

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

			// 添加Advisor链的调用,通过interceptorNames属性进行配置的
			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.
					//如果程序在这里被调用,那么需要加入命名的拦截器advice,并检查这个bean是singleton还是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;
	}

    为 Proxy代理对象配置 Advisor链是在initializeAdvisorchain方法中完成的,这个初始化过程有一个标志位advisorChainInitialized,这个标志用来表示通知器链是否已经初始化。如果已经初始化,那么就不会再初始化,而是直接返回。也就是说,这个初始化的工作发生在应用第一次通过ProxyFactoryBean去获取代理对象的时候。在完成这个初始化之后,接着会读取配置中出现的所有通知器,这个取得通知器的过程就是把通知器的名字交给容器的getBean方法就可以了,这是通过对IoC容器实现的一个回调来完成的。然后把从IoC容器中取得的通知器加入通知器链中,这个是由 addAdvisorOnChainCreation()方法来实现的。

    ok~下面看看他是怎么具体获取代理对象的。 

    回到getObject()方法看看他在单例的情况下是怎么运行的,生成singleton的代理对象在getSingletonInstance()的代码中完成,这个方法是ProxyFactoryBean生成AopProxy代理对象的调用入口。代理对象会封装对target目标对象的调用,也就是说针对 target对象的方法调用行为会被这里生成的代理对象所拦截。具体的生成过程是,首先读取ProxyFactoryBean中的配置,为生成代理对象做好必要的准备,比如设置代理的方法调用接口等。Spring通过AopProxy类来具体生成代理对象。
 

	private synchronized Object getSingletonInstance() {
		if (this.singletonInstance == null) {
			this.targetSource = freshTargetSource();
			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
				//根据AOP框架来判断需要代理的接口
				// 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);
			//这里通过ProxyFactory来生成需要的Proxy
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}



    //通过AopProxy 返回来获取代理对象
	protected Object getProxy(AopProxy aopProxy) {
		return aopProxy.getProxy(this.proxyClassLoader);
	}


	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		//通过AopProxyFactory获取AopProxy,这个AopProxyFactory是在初始化中定义
		//使用的是DefaultAopProxyFactory
		return getAopProxyFactory().createAopProxy(this);
	}


	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			//如果targetClass是接口类,使用JDK来生成Proxy
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			//不是接口类,通过CGLIB生成
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}


    Spring通过AopProxy接口类把AOP代理对象的实现跟框架所分离,它有两个具体的实现:JdkDynamicAopProxy和ObjenesisCglibAopProxy。这两个子类分别是通过CGLIB和JDK来生成需要的Proxy代理对象。

    具体的代理对象生成是通过AopProxyFactory去通过JDK或者CGLIB生成。AopProxy代理对象的生成,需要考虑使用哪种生成方式,如果目标对象是接口类,那么适合使用JDK来生成代理对象,否则 Spring会使用 CGLIB来生成目标对象的代理对象。为了满足不同的代理对象生成的要求,,DefaultAopProxyFactory作为AopProxy对象的生产工厂,可以根据不同的需要生成这两种AopProxy对象。


JDK生成AopProxy代理对象

    这里可以看到AopProxy有两种实现,分别基于JDK的JdkDynamicAopProxy和基于CGLIB的ObjenesisCglibAopProxy。

	@Override
	public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

    JdkDynamicAopProxy使用了JDK的Proxy类来生成代理对象,在生成 Proxy对象之前,首先需要从advised对象中取得代理对象的代理接口配置,然后调用 Proxy的newProxylnstance方法,最终得到对应的Proxy代理对象。在生成代理对象时,需要指明三个参数,一个是类装载器,一个是代理接口,另外一个就是Proxy回调方法所在的对象,这个对象需要实现InvocationHandler接口。这个Invocationhandler接口定义了invoke方法,提供代理对象的回调入口。对于JdkDynamicProxy,它本身实现了InvocationHandler接口和invoke()方法,这个 invoke()方法是Proxy代理对象的回调方法,所以可以使用this来把 JdkDynamicAopProxy指派给Proxy对象,也就是说JdkDynamicAopproxy对象本身,在 Proxy代理的接口方法被调用时,会触发invoke()方法的回调,这个回调方法完成了AOP编织实现的封装。
 

CGLIB生成AopProxy代理对象

    在 AopProxy接口实现中,可以看到使用CGLIB来生成Proxy代理对象,这个Proxy代理对象的生成可以在ObjenesisCglibAopProxy的代码实现中看到,同样是在 AopProxy的接口方法getProxy的实现中完成的。ObjenesisCglibAopProxy继承了CglibAopProxy重写了createProxyClassAndInstance()方法支持不需要通过构造器来实例化对象的功能。

	public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		this.advisedDispatcher = new AdvisedDispatcher(this.advised);
	}

    对于AOP的实现可以看成基础设施准备和AOP运行辅助两个部分组成,这里AopProxy代理对象的生成,可以看做是一个静态的AOP基础设施建立的过程。通过这个准备过程,把代理对象、拦截器这些待调用的部分准备好,等待AOP运行过程中对这些基础设施的使用。

猜你喜欢

转载自blog.csdn.net/qq_37598011/article/details/89971937