spring aop创建bean源码剖析

aop的bean创建代理流程

一.跟踪代码准备

bulid.gradle先添加compile(project(":spring-aspects"))引用

1.Calculator接口

package aop;

public interface Calculator {

	int add(int i, int j);
	int sub(int i, int j);
	int mul(int i, int j);
	int div(int i, int j);
}

2.实现接口类CalculatorImpl

package aop;

public class CalculatorImpl implements Calculator{

	@Override
	public int add(int i, int j) {
		// TODO Auto-generated method stub
		int result =  i+j;
		return result;
	}

	@Override
	public int sub(int i, int j) {
		// TODO Auto-generated method stub
		int result = i - j;
		return result;
	}

	@Override
	public int mul(int i, int j) {
		// TODO Auto-generated method stub
		int result = i * j;
		return result;
	}

	@Override
	public int div(int i, int j) {
		// TODO Auto-generated method stub
		int result = i / j;
		return result;
	}


}

3.日志类LoggingAspect

package aop;
import java.util.Arrays;
import java.util.List;

import javax.management.RuntimeErrorException;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;


public class LoggingAspect {

	public void beforeMethod(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinPoint.getArgs());
		System.out.println(methodName + " begin with " + args);
	}

	public void afterMethod(JoinPoint joinPoint) {
		//获取名字
		String methodName = joinPoint.getSignature().getName();
		//获取参数
		List<Object> args = Arrays.asList(joinPoint.getArgs());
		System.out.println(methodName + " end with " + args);
	}

	public void afterReturning(JoinPoint joinPoint, Object result) {
		String methodName = joinPoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinPoint.getArgs());
		System.out.println("在afterReturning得到返回值:" + result);
		System.out.println(methodName + " end with " + args);
	}

	public void afterThrowing(JoinPoint joinPoint, Exception ex) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println(methodName + " occurs exception:" + ex);
	}

	public Object aroundMethod(ProceedingJoinPoint pjd) {
		Object result = null;
		String methodName = pjd.getSignature().getName();
		//执行目标方法
		try {
			//前置通知
			System.out.println(methodName + " begin with " + Arrays.asList(pjd.getArgs()));
			//执行目标方法
			result = pjd.proceed();
			//后置通知
			System.out.println("在aroundMethod中得到值:" + result);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			//异常通知
			System.out.println("the method occurs exception:" + e);
			throw new RuntimeException(e);
		}
		//后置通知
		System.out.println(methodName + " end with " + Arrays.asList(pjd.getArgs()));
		return result;
	}
}

4.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<!-- 配置bean -->
	<bean id="calculator" class="aop.CalculatorImpl"></bean>
	<!-- 配置切面bean -->
	<bean id="loggingAspect" class="aop.LoggingAspect"></bean>
	<!-- 配置AOP -->
	<aop:config>
		<!-- 配置切点表达式 -->
		<aop:pointcut expression="execution(* aop.Calculator.*(int, int))"
					  id="pointcut"/>
		<!-- 配置切面及通知 -->
		<aop:aspect ref="loggingAspect" order="2">
			<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
			<aop:after method="afterMethod" pointcut-ref="pointcut"/>
		</aop:aspect>
	</aop:config>
</beans>

5.测试入口

package aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml");
		//从IOC容器中获取bean的实例
		Calculator calculator = (Calculator) ctx.getBean(Calculator.class);
		int res = calculator.add(2, 1);
		System.out.println("在主函数中加法计算的结果="+res);
		res = calculator.div(2, 1);
		System.out.println("在主函数中除法计算的结果="+res);
	}
}

二、XmlBeanDefinitionReader解析bean

1.执行方法ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()后,解析aop.xml配置信息,此时beanDefinitiionMap解析到的值为6个值,分别是两个bean、一个aop:pointcut、internalAutoProxyCreator自动创建代理、两个aspectjponitcuntadvisor

 

三.通过finishBeanFactoryInitialization(beanFactory)方法创建bean过程:

1.看方法return BeanUtils.instantiateClass(constructorToUse)//通过反射生成具体的实例化对象

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
		Assert.notNull(ctor, "Constructor must not be null");
		try {
			ReflectionUtils.makeAccessible(ctor);
			if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
				return KotlinDelegate.instantiateClass(ctor, args);
			}
			else {
				Class<?>[] parameterTypes = ctor.getParameterTypes();
				Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
				Object[] argsWithDefaultValues = new Object[args.length];
				//组织参数
				for (int i = 0 ; i < args.length; i++) {
					if (args[i] == null) {
						Class<?> parameterType = parameterTypes[i];
						argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
					}
					else {
						argsWithDefaultValues[i] = args[i];
					}
				}
				//通过反射创建对象
				return ctor.newInstance(argsWithDefaultValues);
			}
		}
		catch (InstantiationException ex) {
			throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
		}
		catch (InvocationTargetException ex) {
			throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
		}
	}

2.再来看方法return ctor.newInstance(argsWithDefaultValues)://通过反射创建对象,到此处与一般的bean都是一样的创建方式,执行完属性填充方法

populateBean(beanName, mbd, instanceWrapper)后,此时的bean与一般的bean没有任何区别

3.再来看exposedObject = initializeBean(beanName, exposedObject, mbd):执行初始化逻辑

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		//如果安全管理器不为空
		if (System.getSecurityManager() != null) {
			//以特权的方式执行回调bean中的aware接口方法
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			//Aware接口处理器,只设置这三个接口BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,设置了beanfactory属性值
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//如果mbd不为空 || mbd不是synthetic,一般是只有aop相关的pointerCut配置或者advice才会将synthetic设置为true
		if (mbd == null || !mbd.isSynthetic()) {
			//将beanpostprocesser运用到给定的现有bean,调用他们的postProcesserBeforeInitialization
			//返回的bean实例可能是原始bean包装器,此处给bean的applicationContext属性赋上值
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//调用初始化方法,先调用bean的initializingBean接口方法,后调用bean的自定义初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			//捕获调用初始化是的异常方法,重新抛出bean创建异常,调用初始化方法失败
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//如果mbd==null || mbd不是Synthetic
		if (mbd == null || !mbd.isSynthetic()) {
			//将BeanPostProcesser运用到给定的bean中
			//返回的bean可能是原始Bean包装器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
        //返回包装后的bean
		return wrappedBean;
	}

判断方法满足,调用他们的postProcesserBeforeInitialization

//如果mbd不为空 || mbd不是synthetic,一般是只有aop相关的pointerCut配置或者advice才会将synthetic设置为true
		if (mbd == null || !mbd.isSynthetic()) {
			//将beanpostprocesser运用到给定的现有bean,调用他们的postProcesserBeforeInitialization
			//返回的bean实例可能是原始bean包装器,此处给bean的applicationContext属性赋上值
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		//初始化返回结果为existingBean
		Object result = existingBean;
		//遍历该工厂创建bean的beanPostProceser
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			//postProcessBeforeInitizlization:在任何bean初始化回调之前
			//将此BeanPostProcesser运用到新bean中,Bean已经填充了属性值,返回的bean可能是原始bean的包装器
			//默认实现按原样返回给定的bean
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			//如果current为null
			if (current == null) {
				//直接返回result,中段其后面的BeanPostProcesser处理
				return result;
			}
			//让result引用processer的返回结果,使其经过BeanPostProcesser后置处理对象的层层包装
			result = current;
		}
		//返回经过BeanPostProcesser后置对象层层包装后的对象result
		return result;
	}

4.initializeBean方法下的判断满足

      //如果mbd==null || mbd不是Synthetic
		if (mbd == null || !mbd.isSynthetic()) {
			//将BeanPostProcesser运用到给定的bean中
			//返回的bean可能是原始Bean包装器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

此时的bean对象依然还是原始对象

applyBeanPostProcessorsAfterInitialization方法调用BeanPostProcessor的postProcessAfterInitialization方法
@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

来看下BeanPostProcessor接口只有两个方法

public interface BeanPostProcessor {
     /*
     * 初始化之前执行的方法
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}


     /*
      * 初始化之后执行的方法
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

此时的getBeanPostProcessors()方法,返回的结果

当遍历到第三个BeanPostProcessor时,当前为AspectJAwareAdvisorAutoProxyCreator,它没有方法postProcessAfterInitialization,但是它继承了

AbstractAdvisorAutoProxyCreator
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator 
AbstractAdvisorAutoProxyCreator 类中也没有postProcessAfterInitialization方法,但是它继承了AbstractAutoProxyCreator 
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator 

最终定位到AbstractAutoProxyCreator类的postProcessAfterInitialization方法

    @Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			/**
			 * 获取当前bean的key:如果beanName不为空,则返回的结果类型为FactoryBean,前面加上&符号;
			 * 若是beanName为空,则使用当前bean的class作为key
			 */
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			//根据key从earlyProxyReferences中查看当前bean是否已经被代理,若是不被代理才进行包装
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				//如果需要被代理,则需要封装指定的bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

此时的bean对象

5.创建代理对象return wrapIfNecessary(bean, beanName, cacheKey)

   protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		//bean已经处理过,直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		//advisedBeans中缓存了所有处理过的bean,已经存在则直接返回
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		/**
		 * isInfrastructureClass()方法判断bean是否为spring系统自带的,自带的则不进行代理
		 * shouldSkip()判断是否忽略当前bean
		 */
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			//放入advisedBeans缓存中
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		//获取当前bean的advices和advisors
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			//对当前bean的状态进行缓存
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			//根据advices和advisors为当前bean生成代理对象
			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;
	}

通过方法Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);获取到当前bean的advices和advisors,获取到三个,一个ExposeInvocationInterceptor、两个我们xml中定义的方法

重点方法生成代理对象

           //根据advices和advisors为当前bean生成代理对象
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//创建代理

6.重点分析创建方法createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)),构建增强器

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

		//给bean设置暴露属性
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		//创建代理对象
		ProxyFactory proxyFactory = new ProxyFactory();
		//获取当前对象的相关属性
		proxyFactory.copyFrom(this);
        //判断给的bean是否应该使用它的targetClass,而不是接口代理
		if (!proxyFactory.isProxyTargetClass()) {
			//判断是使用Jdk动态代理,还是使用CgLib代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {//添加代理接口
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		//构建增强器
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		//设置要代理的类
		proxyFactory.setTargetSource(targetSource);
		//定制代理
		customizeProxyFactory(proxyFactory);

		//设置代理工程被配置之后,是否还允许修改,默认是false
		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);
	}

再来看其下方法return proxyFactory.getProxy(classLoader);//真正创建代理对象

	public Object getProxy(@Nullable ClassLoader classLoader) {
		//createAopProxy()创建代理工厂
		//分为CglibAopProxy和JdkDynamicAopProxy两种方式
		return createAopProxy().getProxy(classLoader);
	}

再看其下方法:getProxy(classLoader),分为CglibAopProxy/JdkDynamicAopProxy两种方式创建代理

7.使用哪种动态代理方式选择:默认情况,实现了接口使用jdk动态代理,没有实现接口使用cglib动态代理

8.创建完的代理对象,显示使用哪种方式创建的,以及增强代码块

四.从main函数中获取到Calculator,调用计算方法时,源码分析

1.Calculator calculator = (Calculator) ctx.getBean(Calculator.class),获取对象

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}
    @Nullable
	private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
		BeanFactory parent = getParentBeanFactory();
		if (parent instanceof DefaultListableBeanFactory) {
			return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
		}
		else if (parent != null) {
			ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
			if (args != null) {
				return parentProvider.getObject(args);
			}
			else {
				return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
			}
		}
		return null;
	}

2.方法int res = calculator.add(2, 1)调用,首先进入的是JdkDynamicAopProxy的invoke方法

    @Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
}

此时的链

再来看其下的方法

retVal = invocation.proceed()
    @Override
	@Nullable
	public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		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.
			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 {
				// 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);
		}
	}

再执行MethodInterceptor的invoke方法

    @Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		MethodInvocation oldInvocation = invocation.get();
		invocation.set(mi);
		try {
			return mi.proceed();
		}
		finally {
			invocation.set(oldInvocation);
		}
	}

再执行MethodInvocation类的proceed()方法

    @Override
	@Nullable
	public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		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.
			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 {
				// 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);
		}
	}

 

 

 

 

 

 

 

Spring AOP 代理方式
JDK 动态代理:被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术。
CGLib 代理机制:第三方代理技术,CGLib 代理,可以对任何类生成代理。代理的原理是对目标对象进行继承代理。 如果目标对象被 final 修饰,那么该类无法被 CGLib 代理。

JDK 动态代理机制(实现 InvocationHandler 接口,重写 invoke() 方法)

public class JDKProxy implements InvocationHandler{
	private UserDao userDao;

	public JDKProxy(UserDao userDao) {
		this.userDao = userDao;
	}

	public UserDao createProxy() {
		UserDao proxy = (UserDao) Proxy.newProxyInstance(
				userDao.getClass().getClassLoader(),
				userDao.getClass().getInterfaces(),
				this); // this : 类的实例对象,即 new 出来的对象
		return proxy;
	}

	// 调用目标对象的任何一个方法 都相当于调用invoke();
    @Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		if("update".equals(method.getName())){
			// 记录日志:
			System.out.println("日志记录...");
			Object result = method.invoke(userDao, args);
			return result;
		}
		return method.invoke(userDao, args);
	}
}

 

  • CGLib 动态代理机制(实现 MethodInterceptor 接口,重写 intercept() 方法)
/**
 * 使用CGLib生成代理对象
 */
public class CGLibProxy implements MethodInterceptor{
	private ProductDaoImpl productDao;

	public CGLibProxy(ProductDaoImpl productDao) {
		this.productDao = productDao;
	}
	
	public ProductDaoImpl createProxy(){
		// 使用CGLIB生成代理:
		// 1.创建核心类
		Enhancer enhancer = new Enhancer();
		// 2.为其设置父类
		enhancer.setSuperclass(productDao.getClass());
		// 3.设置回调
		enhancer.setCallback(this);
		// 4.创建代理
		return (ProductDaoImpl) enhancer.create();
	}

    @Override
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		if("add".equals(method.getName())){
			System.out.println("日志记录...");
			Object obj = methodProxy.invokeSuper(proxy, args);
			return obj;
		}
		return methodProxy.invokeSuper(proxy, args);
	}
}

消息通知类:
前置通知(before):目标方法运行之前调用
最终通知(after):在目标方法运行之后调用 (无论是否出现异常)
后置通知(after-returning):在目标方法运行之后调用 (未出现异常就会调用)
异常拦截通知(after-throwing):在目标方法运行之后调用(如果出现异常就调用)
环绕通知(around):在目标方法之前和之后都调用 (ProceedingJoinPoint对象 -->> 调用proceed方法)

 

AOP 术语
Joinpoint(连接点) : 所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。
Pointcut(切入点) : 所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
Advice(通知/增强) : 所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能)。
Introduction(引介) : 引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。——类级别的增强。
Target(目标对象) : 代理的目标对象
Weaving(织入) : 是指把增强应用到目标对象来创建新的代理对象的过程,spring 采用动态代理织入,而AspectJ 采用编译期织入和类装载期织入。
Proxy(代理) : 一个类被 AOP 织入增强后,就产生一个结果代理类
Aspect(切面) : 是切入点和通知(引介)的结合

aop源码剖析

多个aop可以使用注解@Order(1)或者实现Ordered接口进行顺序的控制

package com.leusysm.mgr.interceptor;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
 
@Component
@Aspect
@Order(-3)
public class MessageQueueAopAspect1 {
    private static final Logger LOG = LoggerFactory.getLogger(MessageQueueAopAspect1.class);
 
 
    @Pointcut("execution(public * com.leusysm.mgr.controller.CasController.login(..))")
    private void pointCutMethod() {
    }
 
    //声明前置通知
    @Before("pointCutMethod()")
    public void doBefore(JoinPoint point) {
        LOG.info("MessageQueueAopAspect1:doBefore");
        return;
    }
 
    //声明后置通知
    @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
    public void doAfterReturning(JoinPoint point,Object returnValue) {
        LOG.info("MessageQueueAopAspect1:doAfterReturning");
    }
 
    //声明例外通知
    @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        LOG.info("MessageQueueAopAspect1:doAfterThrowing");
    }
 
    //声明最终通知
    @After("pointCutMethod()")
    public void doAfter() {
        LOG.info("MessageQueueAopAspect1:doAfter");
    }
 
    //声明环绕通知
    @Around("pointCutMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        LOG.info("MessageQueueAopAspect1:doAround-1");
        Object obj = pjp.proceed();
        LOG.info("MessageQueueAopAspect1:doAround-2");
        return obj;
    }
 
}
 
package com.leusysm.mgr.interceptor;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
 

@Component
@Aspect
@Order(-4)
public class MessageQueueAopAspect2{
 
    private static final Logger LOG = LoggerFactory.getLogger(MessageQueueAopAspect2.class);
 
    @Pointcut("execution(public * com.leusysm.mgr.controller.CasController.login(..))")
    private void pointCutMethod() {
    }
 
 
    //声明前置通知
    @Before("pointCutMethod()")
    public void doBefore(JoinPoint point) {
        LOG.info("MessageQueueAopAspect2:doBefore");
        return;
    }
 
    //声明后置通知
    @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
    public void doAfterReturning(JoinPoint point,Object returnValue) {
        LOG.info("MessageQueueAopAspect2:doAfterReturning");
    }
 
    //声明例外通知
    @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        LOG.info("MessageQueueAopAspect2:doAfterThrowing");
    }
 
    //声明最终通知
    @After("pointCutMethod()")
    public void doAfter() {
        LOG.info("MessageQueueAopAspect2:doAfter");
    }
 
    //声明环绕通知
    @Around("pointCutMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        LOG.info("MessageQueueAopAspect2:doAround-1");
        Object obj = pjp.proceed();
        LOG.info("MessageQueueAopAspect2:doAround-2");
        return obj;
    }
 
}
 

根据order的不同执行顺序不一样。下面是两个aop的执行顺序,order越小优先级越高

从上面的测试我们看到,Order越小越是最先执行,但更重要的是最先执行的最后结束。

单个AOP执行顺序:Around-start-->Before-->Around-end-->After-->AfterReturn

多个AOP拦截同一个点,会根据order的优先级执行:

Around-start-->Before-->(嵌入优先级低的AOP执行流程)-->Around-end-->After-->AfterReturn

Spring AOP就是面向切面编程,什么是切面,画一个图来理解下:

 由此得出:spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。

 如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值