做网站要多,德阳公司做网站,新乡专业网站制作,500亿网站建设文章目录 一、概念1、AOP是什么#xff1f;2、相关概念1#xff09;目标对象Target2#xff09;通知Advice3#xff09;连接点Joinpoint4#xff09;切点Pointcut5#xff09;切面Aspect6#xff09;织入Weaving 二、分析三、实现1、实现Advice1#xff09;前置通知22、相关概念1目标对象Target2通知Advice3连接点Joinpoint4切点Pointcut5切面Aspect6织入Weaving 二、分析三、实现1、实现Advice1前置通知2后置通知3环绕通知4异常通知5最终通知 2、实现Pointcut1分析2具体代码实现 3、实现Aspect1分析2具体代码实现 4、织入实现1分析2具体代码实现 四、最终完整版本五、总结 一、概念
1、AOP是什么
AOP[Aspect Oriented Programming] 面向切面编程在不改类代码的情况下对类方法进行增强操作 切面将那些和业务无关的公共逻辑封装起来方面使用 横切一刀剖开对象的封装将多个类的公共行为封装到一个可重用的模块组成一个切面 2、相关概念
1目标对象Target
目标对象是实际执行程序的对象需要被代理的类切面通过代理目标对象来添加额外的行为。
2通知Advice
在什么时候进行增强功能
前置后置环绕异常最终
3连接点Joinpoint
可以被选择来进行增强的点包含切点
4切点Pointcut
需要增强的点
5切面Aspect
Advice和Pointcut组合成了切面定义了在何时和何地完成增强功能
6织入Weaving
将切面应用到目标对象的方法上并创建代理对象的过程可以在编译时、类加载时或运行时进行。
二、分析
所以我们通过AOP来实现对类方法功能的增强。在已有类和方法的情况下我们需要写的就是在什么时候进行增强方法前还是方法后…也就是Advice需要对什么方法进行增强也就是Pointcut两种共同组成了切面确定了时间和地点从而进行功能增强。
Advice 用户性用户根据需求编写 可选时机可在方法前、后、异常时进行功能增强 多重性一个切入点可以有多个增强可以在方法前以及方法后同时增强 Pointcut 用户性用户可灵活指定 多点性可以选择在多个点上进行增强 Weaving无入侵性不修改原类的代码 在Spring中它已经实现了但这里需要我们自己去实现后面再具体分析下 三、实现
1、实现Advice
定义一个空接口方便后续实现不同的可选时机前置Before、后置AfterReturn、环绕Around、异常Throwing、最终After
public interface Advice {
}分析一波无论什么通知都是对方法进行增强所以基本都需要方法的相关信息后面来看看具体实现
1前置通知
作用在方法执行前进行增强
所需的参数
方法所属对象Object方法本身Method方法的参数Object[]返回值不需要方法都没执行哪来的返回值 具体实现
public interface MethodBeforeAdvice extends Advice {/*** 实现该方法进行前置增强** param method 被增强的方法* param args 方法的参数* param target 被增强的目标对象* throws Throwable*/void before(Method method, Object[] args, Object target) throws Throwable;
}2后置通知
作用在方法执行成功返回后进行增强
所需的参数
方法所属对象Object方法本身Method方法的参数Object[]方法的返回值Object可能有也可能没有得看看是否允许在After中更改返回的结果如果规定只可用、不可修改返回值就不需要返回值允许更改才需要返回值
具体实现
public interface AfterReturningAdvice extends Advice {/*** 实现该方进行后置增强** param returnValue 返回值* param method 被增强的方法* param args 方法的参数* param target 方法的所属对象* throws Throwable*/void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
}3环绕通知
作用包裹方法进行增强
所需的参数
方法所属对象Object方法本身Method方法的参数Object[]方法的返回值Object方法将由它来执行它需要返回方法的返回值
具体实现
public interface MethodInterceptor extends Advice {/*** 实现该方法进行环绕前置、后置增强、异常处理增强** param method 被增强的方法* param args 方法的参数* param target 方法所属对象* return Object 返回值* throws Throwable*/Object invoke(Method method, Object[] args, Object target) throws Throwable;
}
4异常通知
作用对方法执行时的异常进行增强处理
参数说明
必须的参数Exception
可能需要的参数 方法所属对象Object方法本身Method方法的参数Object[]
具体实现
public interface ThrowsAdvice extends Advice {/*** 实现该方法进行异常处理增强** param method 被增强的方法* param args 方法的参数* param target 方法所属对象* param ex 抛出的异常* return*/void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable;
}5最终通知
作用在方法执行后进行增强
所需的参数
方法所属对象Object方法本身Method方法的参数Object[]方法的返回值Object可能有也可能没有得看看是否允许在After中更改返回的结果如果规定只可用、不可修改返回值就不需要返回值允许更改才需要返回值
具体实现
public interface AfterAdvice extends Advice {/*** 实现该方法进行最终增强** param returnValue 返回值* param method 被增强的方法* param args 方法的参数* param target 方法的所属对象* throws Throwable*/void after(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
}通知类的类图类图如下
2、实现Pointcut
其实就是指定要增强的方法
1分析
那么我们应该怎么指定要增强的方法要求满足用户灵活控制并且程序也能轻松识别
首先应该怎么描述指定一个方法方法可能有重载的情况如下 com.forlan.test(int,string) com.forlan.test(int) 还要满足灵活控制以及支持多个点增强情况可能有如下很多种 某包下某个类的某个方法 某包下某个类的所有方法 某包下所有类的所有方法 某包下以Service结尾的类中以xx开头的方法 … 所以我们需要一个表达式能够灵活地去描述匹配到目标方法名类似包名.类名.方法名(参数类型) 需要满足的要求
包名、类名、方法名支持模糊匹配参数类型可能有多个
所以可以使用AspectJ表达式官网http://www.eclipse.org/aspectj 语法格式 execution([访问权限类型] 返回值类型 [全限定性类名] 方法名(参数名) [抛出的异常类型]) execution表达式中就是方法的签名 表达式中加[ ]的部分表示可省略 各部分用空格分开 可以使用的符号 *0至多个字符 …用在方法参数中表示任意多个参数用在包名后表示当前包及其子包路径 用在类名后表示当前类及子类用在接口后表示接口及实现类 例子
任意公共方法execution(public * *(. .))任何一个以“set”开始的方法execution(* set *(. .))定义在service包里的任意类的任意方法execution(* com.forlan.service..(. .))
所以最终就是用户通过指定AspectJ表达式程序去解析表达式中需要增强的类中的方法。
2具体代码实现
定义一个接口提供需要匹配的类和方法
public interface Pointcut {boolean matchsClass(Class? targetClass);boolean matchsMethod(Method method, Class? targetClass);
}定义实现类用aspectj工具包识别表达式大概思路就是先匹配类再匹配方法
public class AspectJExpressionPointcut implements Pointcut {private static PointcutParser pp PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();private String expression;private PointcutExpression pointcutExpression;public AspectJExpressionPointcut(String expression) {super();this.expression expression;pointcutExpression pp.parsePointcutExpression(expression);}Overridepublic boolean matchsClass(Class? targetClass) {return pointcutExpression.couldMatchJoinPointsInType(targetClass);}Overridepublic boolean matchsMethod(Method method, Class? targetClass) {ShadowMatch sm pointcutExpression.matchesMethodExecution(method);return sm.alwaysMatches();}public String getExpression() {return expression;}}3、实现Aspect
1分析
其实就是前面的Advice和Pointcut的组合
通过Advice确定何时进行什么增强通过Pointcut确定何地目标方法进行增强
我们参考Spring定义Advisor来描述组合Advice和Pointcut 在Spring框架中Advisor是一个用于提供切面Aspect功能的对象。它用于定义切入点Pointcut和通知Advice之间的关系。通常Advisor会根据切入点来确定在何时和何地应用通知。通知可以是在方法执行前、执行后或抛出异常时执行的代码。Advisor可以通过配置或编程方式添加到Spring应用程序中以实现横切关注点的功能例如日志记录、事务管理等。 2具体代码实现
定义一个接口
public interface Advisor {String getAdviceBeanName();String getExpression();
}定义基于切点的接口
public interface PointcutAdvisor extends Advisor {Pointcut getPointcut();
}基于AspectJ切点的实现类
public class AspectJPointcutAdvisor implements PointcutAdvisor {private String adviceBeanName;private String expression;private Pointcut pointcut;public AspectJPointcutAdvisor(String adviceBeanName, String expression) {super();this.adviceBeanName adviceBeanName;this.expression expression;this.pointcut new AspectJExpressionPointcut(this.expression);}Overridepublic Pointcut getPointcut() {return this.pointcut;}Overridepublic String getAdviceBeanName() {return this.adviceBeanName;}Overridepublic String getExpression() {return this.expression;}
}实现的类图结构如下
4、织入实现
其实就是把用户提供的增强方法加到指定的方法上
1分析
在什么时候织入 在Bean初始化后对其进行增强 如何实现织入 主要讨论的是运行时织入可以通过使用动态代理或字节码生成技术在目标对象的方法执行前后插入切面代码。 如何确定Bean需要增强 Bean类及其方法和与切面进行匹配匹配到表示需要增强 如果增强的方法写在Bean生命周期过程中也就是在BeanFactory中找到对应的方法在方法前、后等位置写代码这样的话代码会越来越复杂不好拓展 考虑到拓展性在不修改BeanFactory中代码的情况下实现灵活扩展可以考虑使用观察者模式在各个节点加入扩展点,增加一个Bean的处理器BeanPostProcessor先注册到BeanFactory后面在初始化前后的处理中再遍历执行BeanPostProcessor增强1 总的来说BeanFactory实现相关Bean的增强操作需要做两件事
创建相关的BeanPostProcessor并注册到BeanFactory中BeanFactory在初始化Bean的前后增加判断判断是否有相关BeanPostProcessor如果有就进行相关的增强处理
2具体代码实现
定义BeanPostProcessor接口定义初始化之前和初始化之后要执行的方法默认返回原始bean表示不增强
public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName) throws Throwable {return bean;}default Object postProcessAfterInitialization(Object bean, String beanName) throws Throwable {return bean;}
}让BeanFactory支持注册BeanPostProcessor
void registerBeanPostProcessor(BeanPostProcessor beanPostProcessor);DefaultBeanFactory实现支持注册BeanPostProcessor并且在Bean对象初始化前后校验是否需要进行增强主要调整doCreateInstance方法
// Bean增强相关处理类
private ListBeanPostProcessor beanPostProcessors Collections.synchronizedList(new ArrayList());Override
public void registerBeanPostProcessor(BeanPostProcessor beanPostProcessor) {this.beanPostProcessors.add(beanPostProcessor);
}private Object doCreateInstance(String beanName, BeanDefinition bd) throws Exception {Class? beanClass bd.getBeanClass();Object instance null;if (beanClass ! null) {if (StringUtils.isBlank(bd.getFactoryMethodName())) {// 构造方法来构造对象instance this.createInstanceByConstructor(bd);} else {// 静态工厂方法instance this.createInstanceByStaticFactoryMethod(bd);}} else {// 工厂bean方式来构造对象instance this.createInstanceByFactoryBean(bd);}// 赋值前暴露半成品对象this.doEarlyExposeBuildingBeans(beanName, instance);// 支持属性依赖this.setPropertyDIValues(bd, instance);// 赋完值移除this.removeEarlyExposeBuildingBeans(beanName);// bean初始化前的处理instance this.applyPostProcessBeforeInitialization(instance, beanName);// 执行初始化方法this.doInit(bd, instance);// bean初始化后的处理instance this.applyPostProcessAfterInitialization(instance, beanName);return instance;}private Object applyPostProcessBeforeInitialization(Object bean, String beanName) throws Exception {for (BeanPostProcessor bpp : this.beanPostProcessors) {bean bpp.postProcessBeforeInitialization(bean, beanName);}return bean;}private Object applyPostProcessAfterInitialization(Object bean, String beanName) throws Exception {for (BeanPostProcessor bpp : this.beanPostProcessors) {bean bpp.postProcessAfterInitialization(bean, beanName);}return bean;}实现织入通过创建Bean对应的代理对象来处理 代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下一个对象不适合或者不能直接引用另一个对象而代理对象可以在调用者和目标对象之间起到中介的作用。 方式有JDK动态代理Cglib动态代理Javassist、ASM 通过 抽象和 面向接口编程来设计一套支持不同代理实现的代码类图结构如下 定义上层接口
public interface AopProxy {Object getProxy();Object getProxy(ClassLoader classLoader);
}JDK动态代理实现AopProxy同时实现InvocationHandler创建动态代理对象重写invoke方法来处理代理对象的方法调用
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {private String beanName;private Object target;private ListAdvisor matchAdvisors;private BeanFactory beanFactory;public JdkDynamicAopProxy(String beanName, Object target, ListAdvisor matchAdvisors, BeanFactory beanFactory) {this.beanName beanName;this.target target;this.matchAdvisors matchAdvisors;this.beanFactory beanFactory;}Overridepublic Object getProxy() {return this.getProxy(target.getClass().getClassLoader());}Overridepublic Object getProxy(ClassLoader classLoader) {return Proxy.newProxyInstance(classLoader, target.getClass().getInterfaces(), this);}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return AopProxyUtils.applyAdvices(target, method, args, matchAdvisors, proxy, beanFactory);}
}Cglib动态代理实现AopProxy同时实现MethodInterceptor 创建动态代理对象重写intercept方法对目标对象的方法进行拦截和增强
public class CglibDynamicAopProxy implements AopProxy, MethodInterceptor {private static Enhancer enhancer new Enhancer();private String beanName;private Object target;private ListAdvisor matchAdvisors;private BeanFactory beanFactory;public CglibDynamicAopProxy(String beanName, Object target, ListAdvisor matchAdvisors, BeanFactory beanFactory) {this.beanName beanName;this.target target;this.matchAdvisors matchAdvisors;this.beanFactory beanFactory;}Overridepublic Object getProxy() {return this.getProxy(target.getClass().getClassLoader());}Overridepublic Object getProxy(ClassLoader classLoader) {Class? superClass this.target.getClass();enhancer.setSuperclass(superClass);enhancer.setInterfaces(this.getClass().getInterfaces());enhancer.setCallback(this);Constructor? constructor null;try {constructor superClass.getConstructor(new Class?[] {});} catch (NoSuchMethodException | SecurityException e) {}if (constructor ! null) {return enhancer.create();} else {BeanDefinition bd ((DefaultBeanFactory) beanFactory).getBeanDefinition(beanName);// 利用BeanDefinition的缓存直接拿到真正的参数return enhancer.create(bd.getConstructor().getParameterTypes(), bd.getConstructorArgumentRealValues());}}Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {return AopProxyUtils.applyAdvices(target, method, args, matchAdvisors, proxy, beanFactory);}
}创建代理对象的过程中可能需要有参构造参数这个在前面创建原Bean的时候已经解析过我们调整下BeanDefinition增加缓存
/*** 获取真正的入参*/
Object[] getConstructorArgumentRealValues();
void setConstructorArgumentRealValues(Object[] values);GenericBeanDefinition
private ThreadLocalObject[] realConstructorArgumentValues new ThreadLocal();Override
public Object[] getConstructorArgumentRealValues() {return realConstructorArgumentValues.get();
}Override
public void setConstructorArgumentRealValues(Object[] values) {realConstructorArgumentValues.set(values);
}调整DefaultBeanFactory的createInstanceByConstructor方法在解析完有参构造参数后缓存一份到BeanDefinition
private Object createInstanceByConstructor(BeanDefinition bd) throws Exception {// 1、获取参数值Object[] args this.getConstructorArgumentValues(bd);// 缓存构造参数方便后续创建代理bd.setConstructorArgumentRealValues(args);// 2、确定调用什么构造方法来创建实例Constructor constructor this.determineConstructor(bd, args);return constructor.newInstance(args);
}不管用哪种方式来生成代理对象最终增强的逻辑代码是一样的那么就可以提炼抽取为公共代码
public class AopProxyUtils {/*** 对方法应用增强*/public static Object applyAdvices(Object target, Method method, Object[] args, ListAdvisor matchAdvisors,Object proxy, BeanFactory beanFactory) throws Throwable {// 获取要对当前方法进行增强的adviceListObject advices AopProxyUtils.getShouldApplyAdvices(target.getClass(), method, matchAdvisors, beanFactory);if (CollectionUtils.isEmpty(advices)) {return method.invoke(target, args);} else {// 存在增强的advice进行增强AopAdviceChainInvocation chain new AopAdviceChainInvocation(proxy, target, method, args, advices);return chain.invoke();}}private static ListObject getShouldApplyAdvices(Class? beanClass, Method method, ListAdvisor matchAdvisors, BeanFactory beanFactory) throws Exception {if (CollectionUtils.isEmpty(matchAdvisors)) {return null;}ListObject advices new ArrayList();for (Advisor ad : matchAdvisors) {if (ad instanceof PointcutAdvisor) {if (((PointcutAdvisor) ad).getPointcut().matchsMethod(method, beanClass)) {advices.add(beanFactory.getBean(ad.getAdviceBeanName()));}}}return advices;}
}对于多种通知类型有执行顺序我们通过责任链模式来实现
public class AopAdviceChainInvocation {private static Method invokeMethod;static {try {invokeMethod AopAdviceChainInvocation.class.getMethod(invoke, null);} catch (NoSuchMethodException | SecurityException e) {e.printStackTrace();}}private Object proxy;private Object target;private Method method;private Object[] args;private ListObject advices;public AopAdviceChainInvocation(Object proxy, Object target, Method method, Object[] args, ListObject advices) {super();this.proxy proxy;this.target target;this.method method;this.args args;this.advices advices;}// 责任链执行记录索引号private int index 0;public Object invoke() throws Throwable {if (index this.advices.size()) {Object advice this.advices.get(index);if (advice instanceof MethodBeforeAdvice) {// 执行前置增强((MethodBeforeAdvice) advice).before(method, args, target);} else if (advice instanceof MethodInterceptor) {// 执行环绕增强这里的method和对象是invoke方法和链对象return ((MethodInterceptor) advice).invoke(invokeMethod, null, this);} else if (advice instanceof AfterReturningAdvice) {// 执行后置增强返回成功才触发Object returnValue this.invoke();((AfterReturningAdvice) advice).afterReturning(returnValue, method, args, target);return returnValue;} else if (advice instanceof AfterAdvice) {// 执行最终增强Object returnValue null;try {returnValue this.invoke();} finally {((AfterAdvice) advice).after(returnValue, method, args, target);}return returnValue;} else if (advice instanceof ThrowsAdvice) {try {return this.invoke();} catch (Exception e) {// 执行异常增强发生异常才触发((ThrowsAdvice) advice).afterThrowing(method, args, target, e);}}return this.invoke();} else {return method.invoke(target, args);}}
}定义AOP代理工厂方便我们获取不同的代理
public interface AopProxyFactory {AopProxy createAopProxy(Object bean, String beanName, ListAdvisor matchAdvisors, BeanFactory beanFactory);static AopProxyFactory getDefaultAopProxyFactory() {return new DefaultAopProxyFactory();}
}具体AOP代理工厂实现
public class DefaultAopProxyFactory implements AopProxyFactory {Overridepublic AopProxy createAopProxy(Object bean, String beanName, ListAdvisor matchAdvisors, BeanFactory beanFactory) {// 是该用jdk动态代理还是cglibif (shouldUseJDKDynamicProxy(bean, beanName)) {return new JdkDynamicAopProxy(beanName, bean, matchAdvisors, beanFactory);} else {return new CglibDynamicAopProxy(beanName, bean, matchAdvisors, beanFactory);}}private boolean shouldUseJDKDynamicProxy(Object bean, String beanName) {// 有实现接口就用JDK,没有就用Cglibreturn bean.getClass().isInterface();}
}前面我们的增强通过代理来实现那什么时候需要进行增强在什么地方增强就需要获取我们定义的切面、切点、通知类这些都在Spring容器中了我们只需要获取到BeanFactory对象就能拿到它们那么怎么在BeanPostProcessor中获取到这个对象我们可以参考Spring的做法 在Springboot中通过实现这些Aware接口Spring容器会在适当的时候将相应的资源或环境注入到实现类中使其能够访问和利用这些资源或环境。例如实现BeanFactoryAware接口的类可以获取对BeanFactory的引用。 定义Aware接口Aware的意思就是意识xxxAware可以理解为具备xxx意识
public interface Aware {}定义BeanFactoryAware继承Aware接口
public interface BeanFactoryAware extends Aware {void setBeanFactory(BeanFactory bf);
}调整DefaultBeanFactory的registerBeanPostProcessor在注册BeanPostProcessor的同时判断实现了BeanFactoryAware接口的话就把当前BeanFactory设置给BeanPostProcessor方便BeanPostProcessor去使用
Override
public void registerBeanPostProcessor(BeanPostProcessor beanPostProcessor) {this.beanPostProcessors.add(beanPostProcessor);if (beanPostProcessor instanceof BeanFactoryAware) {((BeanFactoryAware) beanPostProcessor).setBeanFactory(this);}
}新增AdvisorAutoProxyCreator类实现BeanPostProcessor和BeanFactoryAware重写postProcessAfterInitialization进行Bean初始化后的增强重写setBeanFactory在注册的时候自动设置BeanFactory方便后续使用
public class AdvisorAutoProxyCreator implements BeanPostProcessor, BeanFactoryAware {private BeanFactory beanFactory;private ListAdvisor advisors;// 标识是否获取过了所有的Advisorsprivate volatile boolean gettedAllAdvisors false;Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {// 跳过指定类型的增强if (bean instanceof Advisor || bean instanceof Advice) {return bean;}// 判断Bean是否需要增强根据配置的切面找出匹配的切面ListAdvisor matchAdvisors getMatchedAdvisors(bean, beanName);// 如有匹配的切面创建代理来实现增强if (CollectionUtils.isNotEmpty(matchAdvisors)) {bean this.createProxy(bean, beanName, matchAdvisors);}return bean;}private ListAdvisor getMatchedAdvisors(Object bean, String beanName) throws Exception {// 第一次执行该方法先从BeanFactory中得到用户配置的所有切面Advisorif (!gettedAllAdvisors) {synchronized (this) {if (!gettedAllAdvisors) {advisors this.beanFactory.getBeansOfTypeList(Advisor.class);gettedAllAdvisors true;}}}// 如果没有配置切面直接返回if (CollectionUtils.isEmpty(this.advisors)) {return null;}// 有配置切面获取Bean的类以及所有的方法Class? beanClass bean.getClass();ListMethod allMethods this.getAllMethodForClass(beanClass);// 用于存放匹配的AdvisorListAdvisor matchAdvisors new ArrayList();// 遍历Advisor来匹配for (Advisor advisor : this.advisors) {if (advisor instanceof PointcutAdvisor) {if (isPointcutMatchBean((PointcutAdvisor) advisor, beanClass, allMethods)) {matchAdvisors.add(advisor);}}}return matchAdvisors;}// 获得本类以及所实现的接口的方法private ListMethod getAllMethodForClass(Class? beanClass) {ListMethod allMethods new LinkedList();SetClass? classes new LinkedHashSet(ClassUtils.getAllInterfacesForClassAsSet(beanClass));classes.add(beanClass);for (Class? clazz : classes) {Method[] methods ReflectionUtils.getAllDeclaredMethods(clazz);for (Method m : methods) {allMethods.add(m);}}return allMethods;}private boolean isPointcutMatchBean(PointcutAdvisor pa, Class? beanClass, ListMethod methods) {Pointcut p pa.getPointcut();// 首先判断类是否匹配if (!p.matchsClass(beanClass)) {return false;}// 再判断方法是否匹配for (Method method : methods) {if (p.matchsMethod(method, beanClass)) {return true;}}return false;}private Object createProxy(Object bean, String beanName, ListAdvisor matchAdvisors) throws Exception {// 通过AopProxyFactory工厂去选择、和创建代理对象return AopProxyFactory.getDefaultAopProxyFactory().createAopProxy(bean, beanName, matchAdvisors, beanFactory).getProxy();}Overridepublic void setBeanFactory(BeanFactory bf) {this.beanFactory bf;}
}四、最终完整版本 五、总结
总的来说Advice制定触发时机和增强功能Pointcut制定触发位置通过AspectJ表达式匹配到目标类的目标方法Aspect将Advice和Pointcut组装在一起方便后续Weaving获取Weaving通过把BeanPostProcessor注册到BeanFactory中在Bean初始化前后预留方法处理BeanPostProcessor实现增强通过Aspect获取Pointcut来判断Bean是否匹配然后通过动态代理来创建代理对象来增强通过去Aspect获取Advice去执行相关的增强使用责任链模式来控制增强多少次。