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里边处理自己的业务逻辑。