AOP的一些原理

可能是因为我一直在做web开发的原因,一直都没觉得AOP有多大的作用,完全可以用拦截器或者过滤器代替,但是这不是不去了解它原理的理由,所以还是看看吧。
AOP的作用很简单就是方法增强,在方法的前后等等地方新增一些操作,比如打印日志或者处理异常什么的,原理也很简单就是动态代理。
代理模式应该都了解了,一个接口,两个实现,一个是原始实现A,一个是功能增强实现B,AOP就是根据A实现和配置来生成B实现,替换IOC中的A实现,从而让我们在使用中都使用增强的B实现。
使用过spring的应该都用过getBean()方法吧,替换就是在这个方法里实现的,在我们getBean的时候,不返回原始的bean,而是返回增强的bean就实现替换了。

源码

开始

如果我们用配置文件的方法来使用AOP的话,一定会使用到DefaultAdvisorAutoProxyCreator类,这个类能让所有的Advisor自动生效,不再需要其他配置:

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />

所以这个类是很关键的,就从这个类开始吧,先看下这个类的继承结构:
在这里插入图片描述
看最左边的分支,看过IOC过程源码的应该很熟悉这个了,IOC过程中有对BeanPostProcessor接口的多次调用,用于功能扩展。

BeanPostProcessor

因为这部分和IOC的源码有很大程度的重合,就不从头开始看了,我们知道创建bean在AbstractAutoWireCapableBeanFactory#DoCreateBean方法中实现的,过程是创建实例->填充属性->初始化,在初始化的步骤里面会调用所有的BeanPostProcessor接口,所以直接看initializeBean方法吧。

  • AbstractAutowireCapableBeanFactory#initializeBean
	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 调用BeanPostProcessor的postProcessBeforeInitialization方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 调用一些初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// 调用BeanPostProcessor的postProcessAfterInitialization方法,这个在这里很关键,AOP就是在这里实现的
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

这个方法很简单,也就是三阶段调用:before、配置的初始化方法、after,关键的还是接口方法的实现,所以我们再回到DefaultAdvisorAutoProxyCreator类中,postProcessAfterInitialization方法的实现在它的父类AbstractAutoProxyCreator中:

  • AbstractAutoProcyCreator#postProcessAfterInitialization
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				// 如果有必要就包裹?(环绕)
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

重点就是在wrapIfNecessary方法,wrap在这里我的理解就是AOP中增强的意思。

  • AbstractAutoProxyCreator#wrapIfNecessary
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 创建代理
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

这个方法里的代码很简单,主要是一些判断之后就创建代理了(如果有advice,就创建代理),重点在createProxy方法里,具体创建代理的方法

  • AbstractAutoProxyCreator#createProxy
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		// 创建代理工厂?
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		// 这里的proxyTargetClass和配置文件里的proxy-target-class有关
		// 当<aop:config proxy-target-class='true' />时,会使用CGLIB来代理接口
		if (proxyFactory.isProxyTargetClass()) {
			// Explicit handling of JDK proxy targets (for introduction advice scenarios)
			if (Proxy.isProxyClass(beanClass)) {
				// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
				for (Class<?> ifc : beanClass.getInterfaces()) {
					proxyFactory.addInterface(ifc);
				}
			}
		}
		else {
			// No proxyTargetClass flag enforced, let's apply our default checks...
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// Use original ClassLoader if bean class not locally loaded in overriding class loader
		ClassLoader classLoader = getProxyClassLoader();
		if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
			classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
		}
		// 主要是这里,获取代理
		return proxyFactory.getProxy(classLoader);
	}

这个接口主要是创建了一个代理工厂,然后往工厂中设置了一些属性,最后通过代理工厂获取代理,看下getProxy方法吧。

  • ProxyFactory#getProxy
	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

这里要先创建一个AopProxy,createAopProxy方法经过一系列调用会到DefaultAopProxyFactory#createAopProxy方法中

  • DefaultAopProxyFactory#createAopProxy
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		// imageCode?不太了解,并且这个是后面版本加进来的,这个值正常情况下肯定是false
		// optimize也不太清楚,默认是false
		// 所以条件就是(proxy-target-class) || (没有接口)
		if (!NativeDetector.inNativeImage() &&
				(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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

这里可以看到AOP默认是使用JDK动态代理的,只有当proxy-target-class配置成true或者没有实现接口才会使用CGLIB代理,主要是因为JDK代理是基于接口的,而CGLIB是基于继承,所以使用CGLIB时,要增强的方法不能用final修饰或者是private的。
createAopProxy方法看完了,我们知道了这里可能返回两种AopProxy,所以getProxy方法肯定有两种不同的实现,这里只看下JDK代理的实现吧,JDK动态代理是用反射实现的。

  • JdkDynamicAopProxy#getProxy
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

我们知道JDK的动态代理需要实现InvocationHandler接口,然后在invoke方法中写具体实现,而在newProxyInstance方法中它的第三个参数就是一个InvocationHandle,这里传的是this,说明JdkDynamicAopProxy本身就是一个InvocationHandle,所以具体实现直接看它的invoke方法就可以了。

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

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			// 前面就不看了,都是一些判断,像什么equales,hashCode方法都是不能增强的
			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;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// 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.
			// chain是空的就说明不需要增强,直接就调用method.invoke方法结束了代理
			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 {
				// We need to create a method invocation...
				// 真正要看的就是这个分支了
				MethodInvocation 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);
			}
		}
	}

到这里好像就结束了,只是粗略地看了一下实现AOP的源码,后续有要补充地再修改吧。

补充

ProxyFactoryBean

责任链模式

advisor

pointcut
advice

BeanPostProcessor

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值