Spring源码深度解析 学习笔记(五)AOP

AOP的基本概念

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

源码分析

面向切面变成,在一个方法执行对前后进行一些操作,并不影响原本方法的执行。
最开始想到的就是 代理模式,将真正对类传递给代理类,代理类执行方法时就是在真实类执行对前后进行一些操作。

获取代理对象(外层)

// ProxyFactoryBean 中的方法,实现类 FactoryBean的接口
public Object getObject() throws BeansException {
	// 初始化通知链,通知链就是我们需要添加的额外操作
	initializeAdvisorChain();
	// 单例
	if (isSingleton()) {
		// 生成单例的代理
		return getSingletonInstance();
	}
	// 原型
	else {
		if (this.targetName == null) {
			logger.info("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");
		}
		// 从需要被拦截的name中链化通知器
		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)) {
					// 通知类,都是从IOC容器里面获取
					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;
}

生成单例的代理

private synchronized Object getSingletonInstance() {
	// 需要代理的beanFactory里面的单例对象
	if (this.singletonInstance == null) {
		// 没有就去beanFactory里面获取
		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));
		}
		// 设置共享单例
		super.setFrozen(this.freezeProxy);
		// ProxyCreateSupport#createAopProxy --> DefaultAopProxyFactory#createAopProxy
		this.singletonInstance = getProxy(createAopProxy());
	}
	return this.singletonInstance;
}

创建AopProxy

protected final synchronized AopProxy createAopProxy() {
	// 监听器设置
	if (!this.active) {
		activate();
	}
	// 这里的 AopProxyFactory 应该是 DefaultAopProxyFactory
	return getAopProxyFactory().createAopProxy(this);
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// 这里先判断之前设置过的interface,就算是普通类如果实现了interface,那么class.getInterface还是可以找到接口的
	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 是 接口类就使用java的动态加载
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		// 不是就使用CGlib
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

得到代理

protected Object getProxy(AopProxy aopProxy) {
	// 使用java动态代理或者Cglib动态代理
	return aopProxy.getProxy(this.proxyClassLoader);
}

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	// 得到增加了原接口总数+3的接口数组
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	// java动态代理,返回代理对象
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

调用代理触发advice

// 这方法在JdkDynamicAopProxy中,也有调用CGLib的方法,但这里只讨论java的动态代理
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	MethodInvocation invocation;
	Object oldProxy = null;
	boolean setProxyContext = false;
	TargetSource targetSource = this.advised.targetSource;
	Object target = null;
	try {
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			// 如果没有实现 equals
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			// 如果没有实现 hashCode方法
			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;
		}
		// 得到目标对象
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);
		// 得到这个方法对应的拦截链
		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.
		if (chain.isEmpty()) {
			// 如果拦截器为空,那就是一个简单的反射操作
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// 构造 ReflectiveMethodInvocation
			invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, 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);
		}
	}
}

得到这个方法对应的拦截链(之前初始化了advice通知)

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
	// 从缓存中获取
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	List<Object> cached = this.methodCache.get(cacheKey);
	// 如果是null,就去加载
	if (cached == null) {
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
				this, method, targetClass);
		this.methodCache.put(cacheKey, cached);
	}
	return cached;
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
		Advised config, Method method, @Nullable Class<?> targetClass) {
	// 实例化advisor适配注册器
	AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
	// config 中已经持有 advisors
	Advisor[] advisors = config.getAdvisors();
	List<Object> interceptorList = new ArrayList<>(advisors.length);
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	Boolean hasIntroductions = null;
	for (Advisor advisor : advisors) {
		if (advisor instanceof PointcutAdvisor) {
			// Add it conditionally.
			PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
			if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actua
				MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
				boolean match;
				if (mm instanceof IntroductionAwareMethodMatcher) {
					if (hasIntroductions == null) {
						hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
					}
					match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntr
				}
				else {
					match = mm.matches(method, actualClass);
				}
				if (match) {
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					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;
}

advisor适配注册器

public final class GlobalAdvisorAdapterRegistry {
	// 解释下registry对由来
	private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
	public static AdvisorAdapterRegistry getInstance() {
		return instance;
	}
}

AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Interceptor[] interceptors = registry.getInterceptors(advisor);

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
	// 初始化拦截器数组
	List<MethodInterceptor> interceptors = new ArrayList<>(3);
	// 从通知器中取得通知
	Advice advice = advisor.getAdvice();
	// 如果是MethodInterceptor类型直接加入
	if (advice instanceof MethodInterceptor) {
		interceptors.add((MethodInterceptor) advice);
	}
	// 如果不是则跟其他3个适配器比较并返回相应的拦截器,实现了各种时机事件的调用
	for (AdvisorAdapter adapter : this.adapters) {
		if (adapter.supportsAdvice(advice)) {
			interceptors.add(adapter.getInterceptor(advisor));
		}
	}
	if (interceptors.isEmpty()) {
		throw new UnknownAdviceTypeException(advisor.getAdvice());
	}
	return interceptors.toArray(new MethodInterceptor[0]);
}

沿着拦截器链前进

public Object proceed() throws Throwable {
	// index从-1开始,并按序递增
	// 如果拦截器迭代完毕了,就使用反射机制,调用target的方法
	// 也就是 interceptorsAndDynamicMethodMatchers.size() = 0的时候
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// 这里对拦截器进行匹配,如果和定义对pointcut匹配就进行执行
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// 如果不匹配就递归执行
			return proceed();
		}
	}
	else {
		// 如果只是一个interceptor,直接调用这个interceptor
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

总结

总的来说AOP的思想就是代理。通过代理在方法执行的上下可以进行通知的织入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值