Spring AOP源码解析(三)创建代理并调用

Spring AOP源码解读 aop 是什么 AOP (Aspect-Oriented Programming,面向切面编程),可以说是 OOP 的补充和完善。OOP 引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP 则显得无能为力。OOP 允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布 阅读详情

一、创建代理准备工作

回顾之前的wrapIfNecessary方法,再获取到匹配的增强器后,Spring就会为拦截的bean创建代理对象:

		//获取匹配的增强器
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		//DO_NOT_PROXY = 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;
		}

创建代理createProxy:

	protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
		//在bean对应的BeanDefinition中添加原Class对象属性(保存bean原本的Class)
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		//获取当前类中配置的属性
		proxyFactory.copyFrom(this);
		
		//检查proxyTargetClass属性
		if (!proxyFactory.isProxyTargetClass()) {
			//检查beanDefinitioin中是否包含preserveTargetClass属性,且属性为true
			//设置是否使用CGLib进行代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				//筛选代理接口并添加到proxyFactory
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		
		//获取增强器(包括前面筛选出来的增强器,以及通过setInterceptorNames中添加的通用增强器,默认为空)
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		for (Advisor advisor : advisors) {
			//将所有增强器添加到proxyFactory
			proxyFactory.addAdvisor(advisor);
		}
		
		//设置需要代理的bean对象信息
		proxyFactory.setTargetSource(targetSource);
		//模版方法,由子类定制化代理
		customizeProxyFactory(proxyFactory);
		//用来控制代理工程被配置后,是否还允许修改代理的配置,默认为false
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		//创建代理对象
		return proxyFactory.getProxy(getProxyClassLoader());
	}

上面代理流程为:

  1. 在BeanDefinition中保存bean原Class对象,因为创建代理后,bean的class会被修改(Spring4中新加入的带你,Spring3中不包含)
  2. 创建ProxyFactory
  3. 设置属性
  4. 过滤目标bean的接口,并添加到ProxyFactory
  5. 获取增强器实例,添加到ProxyFactory中
  6. 创建代理

过滤接口

过滤接口中主要功能是,帮助判断是否使用JDK的动态代理来创建代理。因为JDK动态代理的条件是bean实现了接口,所以Spring会将目标bean实现的接口过滤后添加到ProxyFactory中,方便判断是否使用JDK动态代理,下面是evaluateProxyInterfaces实现:

	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		//获取所有实现的接口
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) {
			//不是Spring内部回调用的接口 && 不是语言内部接口 && 接口定义了一个以上的方法
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;
				break;
			}
		}
		//如果满足上面三个条件,才会将接口添加到proxyFactory
		if (hasReasonableProxyInterface) {
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		//条件不满足,缺少合适的接口,无法使用JDK动态代理,使用CGLib
		else {
			proxyFactory.setProxyTargetClass(true);
		}
	}

下面是过滤条件:

1.Spring内部接口

会排除掉InitializingBean、DisposableBean、Aware接口

	protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
		return (InitializingBean.class == ifc || DisposableBean.class == ifc ||
				ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
	}

2、是否是语言内部接口 isInternalLanguageInterface

	protected boolean isInternalLanguageInterface(Class<?> ifc) {
		return (ifc.getName().equals("groovy.lang.GroovyObject") ||
				ifc.getName().endsWith(".cglib.proxy.Factory"));
	}

其实就是比较类名

3、接口中是否定义了方法

二、创建代理

ProxyFactory.getProxy:

	public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

createAopProxy:

	protected final synchronized AopProxy createAopProxy() {
		//active会在在第一次创建代理后,设为true
		if (!this.active) {
			//设置active为true,并通知监听器(如果没有配置,为空)
			activate();
		}
		//getAopProxyFactory会返回aopProxyFactory变量,默认实现为DefaultAopProxyFactory
		return getAopProxyFactory().createAopProxy(this);
	}

代码流程:

  1. 如果是第一次创建代理,会通知ProxyFactory中注册的监听器
  2. 获取类中定义的aopProxyFactory变量,默认实现为DefaultAopProxyFactory
  3. 通过DefaultAopProxyFactory创建代理对象(会传入当前对象,用于获取配置信息)

DefaultAopProxyFactory-->createAopProxy:

	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			//代理目标bean的Class不能为空
			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.");
			}
			//如果是接口 或者 Class类型为Proxy
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

Spring生成代理对象的方式有两种,JDK动态代理和CGLib,分别生成JdkDynamicAopProxy和ObjenesisCglibAopProxy,从上面代码可以看出Spring的判断条件:

  1. optimize:用来控制通过CGLib创建的代理是否使用激进的优化策略(该仅对CGLib有效)
  2. proxyTargetClass:当属性为true,使用CGLib,设置方式:<aop:aspectj-autoproxy proxy-target-class="true">。
  3. 是否存在代理接口(也就是前面过滤接口一节中,添加进去的接口)
  4. 如果目标类是接口的话,还是会使用JDK的方式进行代理

JDK动态代理与CGLib的区别:

  • JDK只能针对实现了接口的类生成代理
  • CGLib是针对类实现代理,主要通过生成目标类的子类,覆盖其中的方法来达到代理的目的。因此,目标类或方法不能被定义为final

三、获取代理对象

回顾之前getProxy创建代理的代码:

	public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

getAopProxy就是上一节中获取到的AopProxy实例:JdkDynamicAopProxy或ObjenesisCglibAopProxy,后面会调用其getProxy获取代理对象:

	public Object getProxy(ClassLoader classLoader) {
		//log...
		//获取代理接口
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		//检查是否在接口中定义了equals或hashCode方法
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		//创建代理对象
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

上面代码流程:

  1. 获取代理接口
  2. 检查是否在接口中定义了equals或hashCode方法
  3. 使用JDK动态代理Proxy.newProxyInstance创建代理对象

四、方法拦截过程

JDK生成代理对象需要调用return Proxy.newProxyInstance,并传入类加载器、代理接口、以及一个InvocationHandler实例。其中InvocationHandler的invoke方法定义了代理的流程。

上面代码中,传入的InvocationHandler是this,即JdkDynamicAopProxy,该类实现了InvocationHandler接口,下面是其invoke方法实现:

	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 {
			//如果接口中定义了equals或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);
			}
			//opaque属性,表示是否禁止将代理对象转换为Advised对象,默认是false
			//如果调用的方法来自Advised接口
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				//通过反射Method.invoke,调用advised(传入的ProxyFactory实例,该类实现了Advised接口)对应的方法
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
			//为了解决目标对象内部的自我调用无法实施切面中的增强,需要暴露代理对象
			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// 获取目标对象信息
			target = targetSource.getTarget();
			if (target != null) {
				targetClass = target.getClass();
			}

			// 获取当前方法的拦截器链
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// 如果没有任何拦截器,则调用直接对原目标对象调用方法
			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 将拦截器链封装到ReflectiveMethodInvocation,方便使用其proceed进行链式调用拦截器
				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())) {
				// 特殊情况:为了防止方法返回"return this",返回原目标对象,会将返回值替换为代理对象
				retVal = proxy;
			}
			//如果返回类型是基本类型兵器,但是返回结果为null,抛出异常
			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);
			}
		}
	}

代码流程:

  1. 特殊方法的处理,包括equals、hashCode方法以及定义在Advised接口中的方法
  2. 获取方法匹配的增强器,并生成拦截器链并调用
  3. 对方法返回结果进行处理:如果返回“this”,即原目标对象,则会替换为返回代理对象;如果返回结果为null,但返回类型为基本数据类型(int、char等)则抛出异常

1、获取匹配的拦截器:

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
		//缓存的cacheKey,先尝试从缓存获取,不存在再从ProxyFactory中解析
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			//通过实例方法和ProxyFactory中保存的信息,解析出匹配的增强
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}

方法匹配增强器的功能交由advisorChainFactory(DefaultAdvisorChainFactory)完成:

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

		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()) {
			//PointcutAdvisor类型的增强器
			//通过@Aspect加入的增强器类型为InstantiationModelAwarePointcutAdvisorImpl,实现了PointcutAdvisor
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					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;
	}

上面代码首先会遍历拦截增强器,然后根据目标类和目标方法(引介增强外)匹配增强器,如果匹配的话,返回增强器包装的拦截器(Advice)

对于@Aspect注解配置类中,@Before、@After、@AfterThrowing配置的增强会被包装为AspectJMethodBeforeAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice等,在这一步骤中,这些Advice会分别被封装为MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor拦截器。

 

2、创建拦截器链并调用

Spring会在获取到方法匹配的拦截器后,将代理对象、目标对象、调用方法、参数、拦截器等信息封装到ReflectiveMethodInvocation中:

	protected ReflectiveMethodInvocation(
			Object proxy, Object target, Method method, Object[] arguments,
			Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

		this.proxy = proxy;
		this.target = target;
		this.targetClass = targetClass;
		this.method = BridgeMethodResolver.findBridgedMethod(method);
		this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
		this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
	}

然后调用ReflectiveMethodInvocation的proceed方法:

	public Object proceed() throws Throwable {
		//	执行完所有增强后,执行切点方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
		
		//获取下一个拦截器
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			//动态匹配
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				//不匹配则不执行拦截器
				return proceed();
			}
		}
		else {
			// 普通拦截器。比如:MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

通过currentInterceptorIndex记录当前拦截器的索引,每调用一个拦截器就+1,再次调用proceed方法时就会获取下一个拦截器调用。

3、拦截器调用

在获取增强器的过程中,例如@Before注解标注的方法会被封装为AspectJMethodBeforeAdvice,然后会在 1.获取匹配的拦截器 过程中,会被包装为MethodInterceptor(MethodBeforeAdviceInterceptor),下面是Advice转换为MethodInterceptor的过程:

DefaultAdvisorAdapterRegistry.getInterceptors:

	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
		//获取Advice
		Advice advice = advisor.getAdvice();
		//如果Advice实例同时已经实现MethodInterceptor接口,则直接使用
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}
		//需要使用适配器来转换Advice接口
		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[interceptors.size()]);
	}

代码流程:

  1. 如果Advice增强已经实现了MethodInterceptor,则不需要转换,可以直接使用。例如:@After注解标注的增强方法会被表示为AspectJAfterAdvice,该类同时实现了Advice和MethodInterceptor接口,也就是已经在类中规定好了拦截的逻辑。
  2. Advice实现了没有同时实现MethodInterceptor,所以需要使用内置的适配器将Advice增强转换为MethodInterceptor拦截器。

a、内置的Advice适配器

在前面的代码中,将Advice转换为MethodInterceptor的工作是交给this.adapters来完成的,该变量定义如下;

private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);

并且在DefaultAdvisorAdapterRegistry的构造函数中,对该变量进行了初始化填充:

	public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}

可以看到,Spring实现会加入3个默认的是Advice适配器:MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter。

这三个适配器通过support方法,验证是否是否支持传入的Advice对象,如果支持,会将Advice实例封装为对应的MethodInterceptor实例:

MethodBeforeAdviceAdapter:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}

}

AfterReturningAdviceAdapter:

class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof AfterReturningAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
		return new AfterReturningAdviceInterceptor(advice);
	}

}

ThrowsAdviceAdapter:

class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof ThrowsAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		return new ThrowsAdviceInterceptor(advisor.getAdvice());
	}

}

下面是对三种适配器的总结:

适配器支持的Advice接口Advice实现类对应注解
MethodBeforeAdviceAdapterMethodBeforeAdviceAspectJMethodBeforeAdvice@Before
AfterReturningAdviceAdapterAfterReturningAdviceAspectJAfterReturningAdvice@AfterReturning
ThrowsAdviceAdapterThrowsAdvice无无

 

 

 

 

 

下面再来总结一下通过注解配置的增强对应的拦截器:

注解AdviceMethodInterceptor
@BeforeAspectJMethodBeforeAdviceMethodBeforeAdviceInterceptor
@AfterAspectJAfterAdviceAspectJAfterAdvice
@AfterReturningAspectJAfterReturningAdviceAfterReturningAdviceInterceptor
@AfterThrowingAspectJAfterThrowingAdviceAspectJAfterThrowingAdvice
@Around AspectJAroundAdviceAspectJAroundAdvice

 

 

 

 

 

 

 

b、拦截器调用

拦截器的类型有多中,下面我们分析由@Before注解添加的拦截器MethodBeforeAdviceInterceptor。

MethodBeforeAdviceInterceptor定义:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

	private MethodBeforeAdvice advice;

	/**
	 * 将传入的MethodBeforeAdvice封装为MethodBeforeAdviceInterceptor
	 * @param advice the MethodBeforeAdvice to wrap
	 */
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
		return mi.proceed();
	}
}

从invoke方法中可以看到,拦截器会在调用真正方法前,调用MethodBeforeAdvice的before方法,在这一步,也就完成了方法的前置增强。

下面看一下AspectJMethodBeforeAdvice的before实现:

	public void before(Method method, Object[] args, Object target) throws Throwable {
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
	
	protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {
		//将参数绑定后,传入invokeAdviceMethodWithGivenArgs方法执行
		return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
	}

invokeAdviceMethodWithGivenArgs:

	protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
		Object[] actualArgs = args;
		//如果advice增强方法参数为空
		if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
			actualArgs = null;
		}
		try {
			ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
			// 通过反射,调用增强方法
			return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("Mismatch on arguments to advice method [" +
					this.aspectJAdviceMethod + "]; pointcut expression [" +
					this.pointcut.getPointcutExpression() + "]", ex);
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}

 

 

 

 

 

 

 

 

Spring之aop源码解析 aop就是面向切面编程,是为了解耦而生。aop是不仅工作常用而且面试也经常问,所以看aop源码是非常有必要的。在看源码之前,我们先要带着结论去看源码,而不是一上来看的一脸懵逼,一定要先总后分。aop的流程就是在spring的生命周期过程中,会缓存所有的切面,然后在bean初始化的时候,它会找当前bean的所有方法是否跟缓存中的切面有匹配的,如果匹配,说明需要代理并创建代理对象,当调用被增强方法时,执行代理逻辑。本文基于springboot2.3.5.RELEASE,如果有错,欢迎指出。 阅读详情

相关推荐

海思方案定制hi3531dv200/SS528 DVR方案解析:从硬件选型到编解码实战应用

海思方案,Hi3518EV100,Hi3518CV100,Hi3515CV100,Hi3516CV100,Hi3516ECV100,Hi3516D,Hi3516A,Hi3519,Hi3520D,Hi3521A,Hi3535,Hi3531,Hi3536,Hi3536C,Hi3536D,Hi3518EV200,Hi3518EV201,Hi3520DV200,Hi3516CV200,Hi3516CV300,Hi3516AV200,Hi3520DV300,Hi3519V101,sd3403,hi3519av200

1585

SpringAop学习笔记(三)——Aop源码分析

入口 @EnableAspectJAutoProxy @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { 。。。。} AspectJAutoProxyRegistrar.class class AspectJAutoProxyReg

weixin_39555954的博客 268

【Q1/论文复现】:利用 CHARLS 数据库考察抗高血压药物依从性和认知衰退

摘要: 北京大学团队基于CHARLS数据(2011-2018)的纵向研究发现,抗高血压药物高依从性能显著延缓中国45岁及以上社区中老年人的认知衰退。研究表明,坚持服药者7年内全局认知衰退速度降低0.014SD/年,记忆功能衰退减缓0.023SD/年,效果接近正常血压人群水平。研究还提示社会经济地位(SES)可能通过影响用药依从性间接调控认知衰老进程。该成果为高血压管理对认知保护提供了人群级证据,发表于《BMC Medicine》(DOI:10.1186/s12916-025-03949-8)。

dingdianbangni的博客 809

spring5.3 十四:spring AOP源码分析

上一篇分析过spring 通过ProxyFactory来创建代理对象。下面来分析下ProxyFactory的原理上一篇aop的介绍中有提到这两行代码 关键是getProxy方法。 决定好通过那个方式进行代理后,真正调getProxy()方法由下面两个实现类 这里通过jdk的动态代理为例子这个类就是jdk动态代理源码。 这个方法就是放回一个代理对象,不做过多分析。jdk动态代理中,执行代理逻辑和目标方法是通过方法 整个方法的大致流程是:过滤掉equal()、hashcode()这两个方法,这两个方法执行不触

admin522043032的博客 350

鸿蒙系统下基于WebRTC的高效音视频通话开发实战

本文详细介绍了在鸿蒙系统下集成WebRTC技术实现高效音视频通话的实战开发。通过分析鸿蒙分布式软总线与WebRTC低延迟特性的结合优势,提供了从环境搭建、NAPI桥接层开发到音视频采集、P2P连接建立与渲染的完整流程。文章重点探讨了如何利用鸿蒙特性进行性能优化,包括网络自适应、抗抖动策略及系统级调优,旨在帮助开发者构建稳定、低延迟的实时通信应用。

night的博客 572

如何在win11中用双硬盘或移动硬盘装Ubuntu 20.04 双系统

win11 安装双系统

qq_42817360的博客 5139

spring源码深度解析---创建AOP代理之创建代理

创建代理 在获取了所有对应bean的增强后,便可以进行代理的创建了。回到AbstractAutoProxyCreator的wrapIfNecessary方法中,如下图所示: 这里就是创建代码的代码,我们进入到方法内部: protected Object createProxy(Class&lt;?&gt; beanClass, @Nullable String beanName, ...

渔潭的博客 1276

【如何学习CAN总线测试】——AUTOSAR网络管理自动化测试(CAPL源码)

上一章介绍的是AUTOSAR网络管理如何测试、用例设计,对于不满足手工测试的同学,本章就介绍AUTOSAR网络管理自动化测试。

测试领域技术分享 6239

Spring AOP源码解析(中)

上一篇文章中,介绍了Spring中动态代理的使用方式,通过ProxyFactory来创建代理对象,ProxyFactory可以通过addAdvisor()来添加匹配逻辑和代理逻辑,这边文章重点介绍ProxyFactory是如何产生代理对象以及代理对象是如何执行代理逻辑的 一、ProxyFactory生成代理对象 使用ProxyFactory添加advisor,并创建代理对象,调用代理对象的test()方法,代码如下: BeforeAdvisor: public class LizhiBeforeAdviso

sermonlizhi的博客 777

2026从0到1!C#工控机开发实战指南:新手一周就能跑通的完整项目

这篇文章摘要如下: 工业自动化领域工控机开发入门指南,针对零基础开发者提供从环境搭建到项目实战的全流程指导。文章首先解答工控机开发的3个核心问题,比较工控机与普通PC的区别,推荐使用C#作为开发语言。随后详细讲解开发环境配置、四大核心技术栈(通信协议、数据库、UI框架、多线程),并重点演示Modbus TCP通信的实现。最后通过一个完整的温度监控系统项目实战,展示如何用WPF构建实时数据采集界面,包括Modbus通信类编写、数据采集服务实现等关键代码片段。全文采用图解+代码的方式,帮助开发者快速掌握工控系统

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 704

置顶必读(1) | 滚雪球学Oracle教程导航帖,带你弯道超车(持续更新中)

什么是数据库管理系统(DBMS),Oracle在行业中的领先地位Oracle数据库的市场竞争与主要应用场景Oracle数据库的核心功能模块与未来技术发展趋势约束的高级应用:主键、唯一性、外键设计与管理表分区、视图、同义词与序列的最佳实践PL/SQL编程的设计哲学,如何高效使用Oracle SQL DeveloperPL/SQL代码调试与优化技巧RAC集群中的高可用性设计,负载均衡与并行查询的配置集群中的缓存一致性管理。

**My Coding Family** 1万+

Spring:六、ProxyFactory使用

Spring提供了编程式AOP代理方式,而不依赖于Spring Ioc,即ProxyFactory。使用此种方式可以很方便的使用JDK动态代理或CGLIB代理,且支持Advisor chain的使用,可以通过advisor链,增强需要代理的对象方法。

a232884c的博客 1619

宇树G1二次开发资料汇总

宇树科技G1是一款29自由度的商业级人形机器人,配备NVIDIA Jetson Orin NX计算平台和完整SDK生态。本文系统介绍了G1的硬件架构、29个关节配置、传感器外设、双计算单元设计等关键信息,并详细解析了软件生态体系,包括C++/Python SDK、ROS2接口、仿真工具和AI框架。开发者可通过DDS通信实现高层运动控制或底层关节级精确控制,支持快速二次开发。文档提供了网络配置、接口调用示例等实用指南,帮助开发者高效利用该平台进行人形机器人应用开发。

m0_47999117的博客 1316

Spring事务与AOP核心原理深度解析:从源码到实战手写框架

在Java企业级开发中,Spring框架的事务管理与面向切面编程(AOP)是构建高可靠、可维护应用的核心技术。事务管理通过AOP机制,以非侵入方式为方法调用提供声明式事务控制,其底层依赖于动态代理技术实现逻辑织入。理解其原理对于解决实际开发中的事务失效、性能优化等问题至关重要。Spring AOP默认采用CGLIB代理,它通过生成目标类的子类来拦截方法调用,这解释了为何同类内部调用会导致@Transactional注解失效。通过手动实现一个简化版的AOP框架,可以直观体会代理创建、拦截器链与增强逻辑编织的过

weixin_33725807的博客 416

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Spring源码深度解析(AOP功能源码解析)

前言: 有关于Spring,我们最常用的两个功能就是IOC和AOP,前几篇文章从源码级别介绍了Spring容器如何为我们生成bean及bean之间的依赖关系 下面我们接着来看AOP的源码实现。 有关于AOP,我们在面试中也被无数次问到,AOP是什么?AOP有什么作用与优势?AOP在项目中是如何用到的? 这些还都是比较简单的,有些可能会问你AOP的实现是...

恐龙弟旺仔的博客 3万+

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Spring中AOP相关的API及源码解析,原来AOP是这样子的

Spring中AOP相关的API及源码解析 本系列文章: 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configuration注解? 谈谈Spring中的对象跟Bean,你知道Spring怎么创建对象的吗? 这篇文章,我们来谈一谈Spring中的属性注入 推荐阅读: Spring官网阅读 | 总结篇 Spring杂谈 本系列文章将会带你一行行的将Spring的源码吃透,推荐阅读的文章是阅读源码的基础! 因为本文会涉及到动态代理的相关内容,如果对动态代理不

做一个认真的程序员 1万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Spring AOP创建代理对象源码解析

1 工程简介 1.1 pom <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.t

qq_34125999的博客 3932

Spring高手之路21——深入剖析Spring AOP代理对象的创建

本文详细介绍了Spring AOP代理对象的创建过程,分为三个核心步骤:判断是否增强、匹配增强器和创建代理对象。通过源码分析和时序图展示,深入剖析了Spring AOP的工作原理,帮助读者全面理解Spring AOP代理对象的生成机制及其实现细节。

卓越无关环境,保持空杯心态——靡不有初,鲜克有终 1万+

Spring Boot 机制四: AOP 代理机制源码级深度解析(JDK / CGLIB 全链路)

查找当前 Bean 需要应用的增强(Advice)创建代理关键点:代理不是提前创建,而是在初始化后替换 Bean!这意味着Bean 在初始化时是真实对象,但被注入到容器中的是代理对象。@Override维度JDK 代理CGLIB 代理是否需要接口是否性能调用慢,创建快调用快,创建慢是否能代理 final 类否否是否能代理 final 方法否否Spring 默认选择有接口无接口底层原理。

Java、Python、AI、前沿技术等领域的技术总结和经验分享。 7599

Spring AOP源码详细解析

一 . 以下是bean的初始化过程: 注意: 先明白beanPostProcessor的作用,才能够明白aop的加载时机 在bean实例化完成之前和完成之后分别会自动BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法。 二: 介绍一些Spring Aop中一些核心类,大致分为三类: advisorCreator,继承 spring ioc的扩展接口 beanPos...

pengjianglilive的专栏 3678

Spring AOP源码解析

Spring AOP源码解析

qq_41050530的博客 1869

Spring AOP源码学习:创建 AOP 代理

目录 前言 AnnotationAwareAspectJAutoProxyCreator AbstractAutoProxyCreator#postProcessAfterInitialization 代码块1:wrapIfNecessary 代码块2:getAdvicesAndAdvisorsForBean 代码块3:findEligibleAdvisors 代码块4:findAdvisorBeans 代码块5:findCandidateAdvisors 代码块6:buildAspect

程序员囧辉 5203

Spring源码05 - AOP深入代理的创建

Spring源码05 - AOP深入代理的创建

qq_43350524的博客 990

Spring源码解析(九):AOP源码之@Aspect所有相关注解解析

AOP是一种思想,它的实现主要有Spring AOP和AspectJspring AOP底层实现是jdk和cglib动态代理运行期织入借助了AspectJ的语法,即使用了@Aspect @Before @Pointcut等注解来实现AspectJ主要原理是用asm做字节码替换来达到AOP的目的,需要使用专门的编译器ajc编译期、编译期后、类加载期都可以织入AnnotationAwareAspectJAutoProxyCreator主要类图AOP的操作流程都在类中添加注解由@Import注解导入而来。

从基础到源码解析的学习记录 1154

Spring深度学习:AOP创建过程源码解析

本文小豪将带大家深度学习Spring AOP相关知识,包括AOP标签解析及创建代理的底层源码,经过Spring AOP底层源码的解读,以此掌握更多的编程实践方案,同时进一步提升我们的架构能力。AOP实现核心业务和非核心业务的解耦,也提高了系统的可维护性,在Spring中AOP典型的应用就是事务机制,在后续深入学习Spring事务之前,我们有必要先行学习Spring AOP。

Code豪客 1605
上一篇: Spring AOP源码解析(二)获取增强器
finalcola
博客等级 码龄9年 37粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值