Spring AOP的实现

1. AOPAspectJSpring AOP

AOP
AOP 要实现的是在我们原来写的代码的基础上,进行一定的包装,如在方法执行前、方法返回后、方法抛出异常后等地方进行一定的拦截处理或者叫增强处理

AOP 的实现并不是因为 Java 提供了什么神奇的钩子,可以把方法的几个生命周期告诉我们,而是我们要实现一个代理,实际运行的实例其实是生成的代理类的实例

Spring AOP
它基于动态代理来实现。默认地,如果使用接口的,用 JDK 提供的动态代理实现,如果没有接口,使用 CGLIB 实现;Spring AOP 需要依赖于 IOC 容器来管理

AspectJ
属于静态织入,它是通过修改代码来实现的,AspectJ 能干很多 Spring AOP 干不了的事情,它是 AOP 编程的完全解决方案。Spring AOP 致力于解决的是企业级开发中最普遍的 AOP 需求(方法织入),而不是力求成为一个像 AspectJ 一样的 AOP 编程完全解决方案

2. Spring AOP的设计与实现

目前 Spring AOP 一共有三种配置方式,Spring 做到了很好地向下兼容

  • Spring 1.2 基于接口的配置:最早的 Spring AOP 是完全基于几个接口的
  • Spring 2.0 schema-based 配置:Spring 2.0 以后使用 XML 的方式来配置,使用 命名空间 <aop />
  • Spring 2.0 @AspectJ 配置:使用注解的方式来配置,这种方式感觉是最方便的,还有,这里虽然叫做 @AspectJ,但是这个和 AspectJ 其实没啥关系

这里针对Spring 1.2 基于接口的配置完成源码的阅读

Spring AOP的核心技术是动态代理技术,对于AOP的使用者来说只需要配置相关的Bean定义即可,AOP的内部设计为目标建立代理对象,这个代理对象可以通过使用JDKProxy来完成,也可以通过第三方的类生成器CGLIB完成;然后还需要启动代理对象的拦截器来完成各种横切面的织入,这一些列的织入设计是通过一系列Adapter来实现的,通过一系列的Adapter的设计,可以把AOP的横切面设计和Proxy模式有机地结合起来

3. 建立AopProxy代理对象

对于Spring应用,是通过配置和调用SpringProxyFactoryBean来完成代理对象的生成的,在ProxyFactoryBean中,封装了主要代理对象的生成过程,在生成过程中,可以使用JDKProxyCGLIB两种生成方式
在这里插入图片描述

3.1 ProxyFactoryBean

通过上面的类的继承管理可以看到,ProxyFactoryBeanSpring IOC环境中创建AOP应用的底层方法,它完成了具体的AOP代理对象的创建,提供了AOP功能的封装,我们可以通过配置来配置目标对象和切面行为;

ProxyFactoryBeanAOP实现需要依赖JDKCGLIB提供的Proxy特性,之后通过getObject()方法作为入口从FactoryBean中获取对象,对target进行增强的增强处理也通过getObject方法进行封装了

@Override
public Object getObject() throws BeansException {
	//初始化通知器链
	initializeAdvisorChain();
	//对singleton和protoype的类型区分,生成对应的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方法中先对通知器链进行了初始化,通知器链封装了一系列的从配置中读取的拦截器,之后对singletonprotoype的类型区分,生成对应的proxy

这个为proxy代理对象配置Advisor链的过程如下:

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
	//advisorChainInitialized标志位 判断是否已经初始化过
	//只有第一次通过ProxyFactoryBean获取代理对象才会初始化
	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");
		}
		//通过通知器的名字interceptorName在容器中取得通知器加入通知器链
		//取得通知器就是通过容器的getBean方法完成的
		// 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;
}

之后来看生成singleton的代理对象的 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.
			//根据AOP框架来判断需要代理的接口
			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;
}
//通过createAopProxy()返回的AopProxy来得到代理对象
protected Object getProxy(AopProxy aopProxy) {
	return aopProxy.getProxy(this.proxyClassLoader);
}

getSingletonInstance()方法首先读取了ProxyFactoryBean中的配置,比如设置代理的方法的调用接口等,之后通过AopProxy来具体生成代理对象;

AopProxy是个接口类,他有两个实现类,一个是JdkDynamicAopProxy还有一个是CglibAopProxy,显然分别是通过JDKCGLIB来实现需要的Proxy代理对象

AopProxy的生成是通过createAopProxy()方法拿到的,createAopProxy()是基类ProxyCreatorSupprot的方法,在文章的开头的类的继承关系中说过,ProxyCreatorSupprotAdvicedSupport的子类,关于要生成什么样的代理对象的信息都是封装在AdvicedSupport

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

这里使用了AopProxyFactory创建AopProxy,这个AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactory,我们看DefaultAopProxyFactory可以看到,他作为AopProxy对象的生产工厂,会先从AdvisedSupport 对象中取得配置的目标对象,再根据配置信息决定使用JDK还是CGLIB创建代理对象

@Override
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);
	}
}

对于使用JDK生成AopProxy,是在JdkDynamicAopProxy中完成的

@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);
	//调用jdk生成Proxy
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

它首先从advised对象中取得代理对象的代理接口配置,然后调用ProxynewProxyInstance方法,最终得到对应的Proxy对象,对于newProxyInstance方法需要指明三个参数,类加载器,代理接口和Proxy回调方法所在的对象,这个对象需要实现InvocationHandler接口并实现invoke方法,对于JdkDynamicAopProxy来说,它本身就实现了InvocationHandlerinvoke方法,所以这里直接传当前对象就行了

invoke方法是代理对象进行拦截的回调入口,会作为回调函数被触发,通过invoke方法的具体实现来完成对目标方法的调用的拦截和功能增强

invoke方法中把目标对象,拦截器链作为输入创建了ReflectiveMethodInvocation对象完成对AOP实现功能的封装

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	MethodInvocation invocation;
	Object oldProxy = null;
	boolean setProxyContext = false;

	TargetSource targetSource = this.advised.targetSource;
	Class<?> targetClass = null;
	Object target = null;

	try {
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			// The target does not implement the equals(Object) method itself.
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			// The target does not implement the hashCode() method itself.
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			// There is only getDecoratedClass() declared -> dispatch to proxy config.
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			// Service invocations on ProxyConfig with the proxy config...
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;

		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		// May be null. Get as late as possible to minimize the time we "own" the target,
		// in case it comes from a pool.
		//得到目标对象
		target = targetSource.getTarget();
		if (target != null) {
			targetClass = target.getClass();
		}

		// Get the interception chain for this method.
		//拦截器链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		// Check whether we have any advice. If we don't, we can fallback on direct
		// reflective invocation of the target, and avoid creating a MethodInvocation.
		//如果没有设置拦截器链则直接调用target对应的方法
		if (chain.isEmpty()) {
			// We can skip creating a MethodInvocation: just invoke the target directly
			// Note that the final invoker must be an InvokerInterceptor so we know it does
			// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			//有拦截器链则需要拦截器之后才调用目标对象的相应方法,构造一个`ReflectiveMethodInvocation`对象完成对`AOP`实现功能的封装
			// We need to create a method invocation...
			invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			// Proceed to the joinpoint through the interceptor chain.
			//沿着拦截器继续执行
			retVal = invocation.proceed();
		}

		// Massage return value if necessary.
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target &&
				returnType != Object.class && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			// Special case: it returned "this" and the return type of the method
			// is type-compatible. Note that we can't help if the target sets
			// a reference to itself in another returned object.
			retVal = proxy;
		}
		else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException(
					"Null return value from advice does not match primitive return type for: " + method);
		}
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

在上面的方法中先获得了拦截器链

//拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

这个操作是由advised对象完成的,这个advised是一个AdvisedSupport对象,我们可以看到getInterceptorsAndDynamicInterceptionAdvice的实现

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
	//使用了cache
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	List<Object> cached = this.methodCache.get(cacheKey);
	if (cached == null) {
		//由advisorChainFactory完成拦截器链的生成
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
				this, method, targetClass);
		this.methodCache.put(cacheKey, cached);
	}
	return cached;
}

取得拦截器链是由advisorChainFactory完成的,他是一个生成通知器链的工厂,在这里advisorChainFactory被配置为一个DefaultAdvisorChainFactory对象,在DefaultAdvisorChainFactory中实现了拦截器链的获取过程:

@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
		Advised config, Method method, Class<?> targetClass) {

	// This is somewhat tricky... We have to process introductions first,
	// but we need to preserve order in the ultimate list.
	//advisor链已经子啊config中持有了,这里直接使用
	List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
	AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

	for (Advisor advisor : config.getAdvisors()) {
		if (advisor instanceof PointcutAdvisor) {
			// Add it conditionally.
			PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
			if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
				//通过`AdvisorAdapterRegistry`对象实现拦截器的注册,他会对通知进行适配从而获得相应的拦截器
				MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
				//匹配判断
				MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
				if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
					if (mm.isRuntime()) {
						// Creating a new object instance in the getInterceptors() method
						// isn't a problem as we normally cache created chains.
						for (MethodInterceptor interceptor : interceptors) {
							interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
						}
					}
					else {
						interceptorList.addAll(Arrays.asList(interceptors));
					}
				}
			}
		}
		else if (advisor instanceof IntroductionAdvisor) {
			IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
			if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}
		else {
			Interceptor[] interceptors = registry.getInterceptors(advisor);
			interceptorList.addAll(Arrays.asList(interceptors));
		}
	}

	return interceptorList;
}

可以看到,它会通过AdvisorAdapterRegistry对象实现拦截器的注册,他会对通知进行适配从而获得相应的拦截器,这里是单件的GlobalAdvisorAdapterRegistry,他的getIntercept方法为AOP的实现做出了很大的贡献,这个方法封装着advice织入实现的细节;

GlobalAdvisorAdapterRegistry起到的基本上是一个适配器作用,设置了一系列的adapter适配器,正是这些适配器的实现为Spring AOPadvice提供编织功能,先判断取得的advice属于什么类型的advice,从而通过不同的advice类型注册不同的AdviceInterceptor

获得了拦截器链后,在invoke方法中对拦截器链的调用都是通过在ReflectiveMethodInvocation中通过proceed方法实现的,在proceed方法中,会逐个运行拦截器的拦截方法,在运行运行拦截器方法之前会对代理方法完成一个匹配判断,通过这个匹配判断是否满足切面的增强需求,如果满足则从拦截器中得到通知器,并启动通知器的invoke方法进行切面增强

@Override
public Object proceed() throws Throwable {
	//	We start with an index of -1 and increment early.
	//从索引为-1的拦截器开始调用,并按顺序递增
	//如果拦截器链中的拦截器迭代调用完毕,开始使用target的函数,这个函数是通过反射机制完成的
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	//沿着定义好的interceptorOrInterceptionAdvice 链处理
	//获得interceptorOrInterceptionAdvice 
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		//对拦截器进行动态匹配判断 如果匹配则执行advice
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			//不匹配则递归调用proceed,直到所有的拦截器都被运行过为止
			// Dynamic matching failed.
			// Skip this interceptor and invoke the next in the chain.
			return proceed();
		}
	}
	else {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值