来源 | 草捏子

责编 | Carol

封图 | CSDN 付费下载于视觉中国

Spring 作为 Java 中最流行的框架,主要归功于其提供的 IOC 和 AOP 功能。本文将讨论 Spring AOP 的实现。第一节将介绍 AOP 的相关概念,若熟悉可跳过,第二节中结合源码介绍 Spring 是如何实现 AOP 的各概念。

AOP概念

1.1 JoinPoint

进行织入操作的程序执行点。

常见类型:

  • 方法调用(Method Call):某个方法被调用的时点。

  • 方法调用执行(Method Call Execution):某个方法内部开始执行的时点。

    方法调用是在调用对象上的执行点,方法调用执行是在被调用对象的方法开始执行点。

  • 构造方法调用(Constructor Call):对某个对象调用其构造方法的时点。

  • 构造方法执行(Constructor Call Execution):某个对象构造方法内部开始执行的时点。

  • 字段设置(Field Set):某个字段通过 setter 方法被设置或直接被设置的时点。

  • 字段获取(Field Get):某个字段通过 getter 方法被访问或直接被访问的时点。

  • 异常处理执行(Exception Handler Execution):某些类型异常抛出后,异常处理逻辑执行的时点。

  • 类初始化(Class Initialization):类中某些静态类型或静态块的初始化时点。

1.2 Pointcut

Jointpoint 的表述方式。

常见表述方式:

  • 直接指定 Joinpoint 所在方法名称

  • 正则表达式

  • 特定的 Pointcut 表述语言

1.3 Advice

单一横切关注点逻辑的载体,织入到 Joinpoint 的横切逻辑。

具体形式:

  • Before Advice:Joinpoint 处之前执行。

  • After Advice:Joinpoint 处之后执行,细分为三种:

    • After Returning Advice:Joinpoint 处正常完成后执行。

    • After Throwing Advice:Joinpoint 处抛出异常后执行。

    • After Finally Advice:Joinpoint 处正常完成或抛出异常后执行。

  • Around Advice:包裹 Joinpoint,在 Joinpoint 之前和之后执行,具有 Before Advice 和 After Advice 的功能。

  • Introduction:为原有的对象添加新的属性或行为。

1.4 Aspect

对横切关注点逻辑进行模块化封装的 AOP 概念实体,包含多个 Pointcut 和相关 Advice 的定义。

1.5 织入和织入器

织入:将 Aspect 模块化的横切关注点集成到 OOP 系统中。

织入器:用于完成织入操作。

1.6 Target

在织入过程中被织入横切逻辑的对象。

将上述 6 个概念放在一块,如下图所示:

AOP各个概念所处的场景

在了解 AOP 的各种概念后,下面将介绍 Spring 中 AOP 概念的具体实现。

Spring 中的实现

前文提到 AOP 的 Joinpoint 有多种类型,方法调用、方法执行、字段设置、字段获取等。而在 Spring AOP 中,仅支持方法执行类型的 Joinpoint,但这样已经能满足 80% 的开发需要,如果有特殊需求,可求助其他 AOP 产品,如 AspectJ。由于 Joinpoint 涉及运行时的过程,相当于组装好所有部件让 AOP 跑起来的最后一步。所以将介绍完其他概念实现后,最后介绍 Joinpoint 的实现。

2.1 Pointcut

由于 Spring AOP 仅支持方法执行类别的 Joinpoint,因此 Pointcut 需要定义被织入的方法,又因为 Java 中方法封装在类中,所以 Pointcut 需要定义被织入的类和方法,下面看其实现。

Spring 用 org.springframework.aop.Pointcut 接口定义 Pointcut 的顶层抽象。

public interface Pointcut {// ClassFilter用于匹配被织入的类   ClassFilter getClassFilter();// MethodMatcher用于匹配被织入的方法MethodMatcher getMethodMatcher();// TruePoincut的单例对象,默认匹配所有类和方法Pointcut TRUE = TruePointcut.INSTANCE;
}

我们可以看出,Pointcut 通过 ClassFilter 和 MethodMatcher 的组合来定义相应的 Joinpoint。Pointcut 将类和方法拆开来定义,是为了能够重用。例如有两个 Joinpoint,分别是 A 类的 fun() 方法和 B 类的 fun() 方法,两个方法签名相同,则只需一个 fun() 方法的 MethodMatcher 对象,达到了重用的目的,ClassFilter 同理。

下面了解下 ClassFilter 和 MethodMatcher如何进行匹配

ClassFilter 使用matches方法匹配被织入的类,定义如下:

public interface ClassFilter {// 匹配被织入的类,匹配成功返回true,失败返回falseboolean matches(Class<?> clazz);// TrueClassFilter的单例对象,默认匹配所有类ClassFilter TRUE = TrueClassFilter.INSTANCE;
}

MethodMatcher 也是使用 matches方法 匹配被织入的方法,定义如下:

public interface MethodMatcher {// 匹配被织入的方法,匹配成功返回true,失败返回false// 不考虑具体方法参数boolean matches(Method method, Class<?> targetClass);// 匹配被织入的方法,匹配成功返回true,失败返回false// 考虑具体方法参数,对参数进行匹配检查boolean matches(Method method, Class<?> targetClass, Object... args);// 一个标志方法// false表示不考虑参数,使用第一个matches方法匹配// true表示考虑参数,使用第二个matches方法匹配boolean isRuntime();// TrueMethodMatcher的单例对象,默认匹配所有方法MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;}

看到 matches 方法的声明,你是否会觉得有点奇怪,在 ClassFilter 中不是已经对类进行匹配了吗,那为什么在 MethodMatcher 的 matches 方法中还有一个 Class<?> targetClass 参数。请注意,这里的 Class<?> 类型参数将不会进行匹配,而仅是为了找到具体的方法。例如:

public boolean matches(Method method, Class<?> targetClass) {Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);// ...
}

MethodMatcher相比ClassFilter特殊在有两个 matches 方法。将根据 isRuntime() 的返回结果决定调用哪个。而MethodMatcherisRuntime()分为两个抽象类 StaticMethodMatcher(返回false,不考虑参数)和 DynamicMethodMatcher(返回true,考虑参数)。

Pointcut 也因 MethodMathcer 可分为 StaticMethodMatcherPointcut 和 DynamicMethodMatcherPointcut,相关类图如下所示:

Pointcut相关类图

DynamicMethodMatcherPointcut 本文将不介绍,主要介绍下类图中列出的三个实现类。

(1)NameMatchMethodPointcut

通过指定方法名称,然后与方法的名称直接进行匹配,还支持 “*” 通配符。

public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut implements Serializable {// 方法名称private List<String> mappedNames = new ArrayList<>();// 设置方法名称public void setMappedNames(String... mappedNames) {this.mappedNames = new ArrayList<>(Arrays.asList(mappedNames));}@Overridepublic boolean matches(Method method, Class<?> targetClass) {for (String mappedName : this.mappedNames) {// 根据方法名匹配,isMatch提供“*”通配符支持if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) {return true;}}return false;}// ...
}

(2)JdkRegexpMethodPointcut

内部有一个 Pattern 数组,通过指定正则表达式,然后和方法名称进行匹配。

(3)AnnotationMatchingPointcut

根据目标对象是否存在指定类型的注解进行匹配。

2.2 Advice

Advice 为横切逻辑的载体,Spring AOP 中关于 Advice 的接口类图如下所示:

Advice相关类图

(1)MethodBeforeAdvice

横切逻辑将在 Joinpoint 方法之前执行。可用于进行资源初始化或准备性工作。

public interface MethodBeforeAdvice extends BeforeAdvice {void before(Method method, Object[] args, @Nullable Object target) throws Throwable;}

下面来实现一个 MethodBeforeAdvice,看下其效果。

public class PrepareResourceBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("准备资源");}}

定义一个 ITask 接口:

public interface ITask {void execute();}

ITask 的实现类 MockTask

public class MockTask implements ITask {@Overridepublic void execute() {System.out.println("开始执行任务");System.out.println("任务完成");}}

Main 方法如下,ProxyFactoryAdvisor 在后续会进行介绍,先简单了解下,通过ProxyFactory拿到代理类,Advisor用于封装 Pointcut 和 Advice

public class Main {public static void main(String[] args) {MockTask task = new MockTask();ProxyFactory weaver = new ProxyFactory(task);weaver.setInterfaces(new Class[]{ITask.class});// 内含一个NameMatchMethodPointcutNameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();// 指定NameMatchMethodPointcut的方法名advisor.setMappedName("execute");// 指定Adviceadvisor.setAdvice(new PrepareResourceBeforeAdvice());weaver.addAdvisor(advisor);ITask proxyObject = (ITask) weaver.getProxy();proxyObject.execute();}}/** output:
准备资源
开始执行任务
任务完成
**/

可以看出在执行代理对象 proxyObject 的 execute 方法时,先执行了 PrepareResourceBeforeAdvice 中的 before 方法。

(2)ThrowsAdvice

横切逻辑将在 Joinpoint 方法抛出异常时执行。可用于进行异常监控工作。

ThrowsAdvice 接口未定义任何方法,但约定在实现该接口时,定义的方法需符合如下规则

void afterThrowing([Method, args, target], ThrowableSubclass)

前三个参数为 Joinpoint 的相关信息,可省略。ThrowableSubclass 指定需要拦截的异常类型。

例如可定义多个 afterThrowing 方法捕获异常:

public class ExceptionMonitorThrowsAdvice implements ThrowsAdvice {public void afterThrowing(Throwable t) {System.out.println("发生【普通异常】");}public void afterThrowing(RuntimeException e) {System.out.println("发生【运行时异常】");}public void afterThrowing(Method m, Object[] args, Object target, ApplicationException e) {System.out.println(target.getClass() + m.getName() + "发生【应用异常】");}}

修改下 MockTask 的内容:

public class MockTask implements ITask {@Overridepublic void execute() {System.out.println("开始执行任务");// 抛出一个自定义的应用异常throw new ApplicationException();// System.out.println("任务完成");}}

修改下 Main 的内容:

public class Main {public static void main(String[] args) {MockTask task = new MockTask();ProxyFactory weaver = new ProxyFactory(task);weaver.setInterfaces(new Class[]{ITask.class});NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();advisor.setMappedName("execute");// 指定异常监控Adviceadvisor.setAdvice(new ExceptionMonitorThrowsAdvice());weaver.addAdvisor(advisor);ITask proxyObject = (ITask) weaver.getProxy();proxyObject.execute();}}/** output:
开始执行任务
class com.chaycao.spring.aop.MockTaskexecute发生【应用异常】
**/

当抛出 ApplicationException 时,被相应的 afterThrowing 方法捕获到。

(3)AfterReturningAdvice

横切逻辑将在 Joinpoint 方法正常返回时执行。可用于处理资源清理工作。

public interface AfterReturningAdvice extends AfterAdvice {void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;}

实现一个资源清理的 Advice :

public class ResourceCleanAfterReturningAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println("资源清理");}}

修改 MockTask 为正常执行成功, 修改 Main 方法为指定 ResourceCLeanAfterReturningAdvice,效果如下:

/** output:
开始执行任务
任务完成
资源清理
**/

(4)MethodInterceptor

相当于 Around Advice,功能十分强大,可在 Joinpoint 方法前后执行,甚至修改返回值。其定义如下:

public interface MethodInterceptor extends Interceptor {Object invoke(MethodInvocation invocation) throws Throwable;}

MethodInvocation 是对 Method 的封装,通过 proceed() 对方法进行调用。下面举个例子:

public class AroundMethodInterceptor implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("准备资源");try {return invocation.proceed();} catch (Exception e) {System.out.println("监控异常");return null;} finally {System.out.println("资源清理");}}}

上面实现的 invoke 方法,一下子把前面说的三种功能都实现了。

以上 4 种 Advice 会在目标对象类的所有实例上生效,被称为 per-class 类型的 Advice。还有一种 per-instance 类型的 Advice,可为实例添加新的属性或行为,也就是第一节提到的 Introduction。

(5)Introduction

Spring 为目标对象添加新的属性或行为,需要声明接口和其实现类,然后通过拦截器将接口的定义和实现类的实现织入到目标对象中。我们认识下 DelegatingIntroductionInterceptor,其作为拦截器,当调用新行为时,会委派(delegate)给实现类来完成。

例如,想在原 MockTask 上进行加强,但不修改类的声明,可声明一个新的接口 IReinfore

public interface IReinforce {String name = "增强器";void fun();
}

再声明一个接口的实现类:

public class ReinforeImpl implements IReinforce {@Overridepublic void fun() {System.out.println("我变强了,能执行fun方法了");}}

修改下 Main 方法:

public class Main {public static void main(String[] args) {MockTask task = new MockTask();ProxyFactory weaver = new ProxyFactory(task);weaver.setInterfaces(new Class[]{ITask.class});// 为拦截器指定需要委托的实现类的实例DelegatingIntroductionInterceptor delegatingIntroductionInterceptor =new DelegatingIntroductionInterceptor(new ReinforeImpl());weaver.addAdvice(delegatingIntroductionInterceptor);ITask proxyObject = (ITask) weaver.getProxy();proxyObject.execute();// 使用IReinfore接口调用新的属性和行为IReinforce reinforeProxyObject = (IReinforce) weaver.getProxy();System.out.println("通过使用" + reinforeProxyObject.name);reinforeProxyObject.fun();}}/** output:
开始执行任务
任务完成
通过使用增强器
我变强了,能执行fun方法了
**/

代理对象 proxyObject 便通过拦截器,可以使用 ReinforeImpl 实现类的方法。

2.3 Aspect

Spring 中用 Advisor 表示 Aspect,不同之处在于 Advisor 通常只持有一个 Pointcut 和一个 AdviceAdvisor 根据 Advice 分为 PointcutAdvisor 和 IntroductionAdvisor

2.3.1 PointcutAdvisor

常用的 PointcutAdvisor 实现类有:

(1) DefaultPointcutAdvisor

最通用的实现类,可以指定任意类型的 Pointcut 和除了 Introduction 外的任意类型 Advice

Pointcut pointcut = ...; // 任意类型的Pointcut
Advice advice = ...; // 除了Introduction外的任意类型Advice
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(pointcut);
advisor.setAdvice(advice);

(2)NameMatchMethodPointcutAdvisor

在演示 Advice 的代码中,已经有简单介绍过,内部有一个 NameMatchMethodPointcut 的实例,可持有除 Introduction 外的任意类型 Advice

Advice advice = ...; // 除了Introduction外的任意类型Advice
NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();
advisor.setMappedName("execute");
advisor.setAdvice(advice);

(3)RegexpMethodPointcutAdvisor

内部有一个 RegexpMethodPointcut 的实例。

2.3.2 IntroductionAdvisor

只能支持类级别的拦截,和 Introduction 类型的 Advice。实现类有 DefaultIntroductionAdvisor

DelegatingIntroductionInterceptor introductionInterceptor =new DelegatingIntroductionInterceptor(new ReinforeImpl());DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor(introductionInterceptor, IReinforce.class);

2.4 织入和织入器

在演示 Advice 的代码中,我们使用 ProxyFactory 作为织入器

MockTask task = new MockTask();
// 织入器
ProxyFactory weaver = new ProxyFactory(task);
weaver.setInterfaces(new Class[]{ITask.class});
NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();
advisor.setMappedName("execute");
advisor.setAdvice(new PrepareResourceBeforeAdvice());
weaver.addAdvisor(advisor);
// 织入,返回代理对象
ITask proxyObject = (ITask) weaver.getProxy();
proxyObject.execute();

ProxyFactory 生成代理对象方式有:

  • 如果目标类实现了某些接口,默认通过动态代理生成。

  • 如果目标类没有实现接口,默认通过CGLIB生成。

  • 也可以直接设置ProxyFactory生成的方式,即使实现了接口,也能使用CGLIB。

在之前的演示代码中,我们没有启动 Spring 容器,也就是没有使用 Spring IOC 功能,而是独立使用了 Spring AOP。那么 Spring AOP 是如何与 Spring IOC 进行整合的?是采用了 Spring 整合最常用的方法 —— FactoryBean

ProxyFactoryBean 继承了 ProxyFactory 的父类 ProxyCreatorSupport,具有了创建代理类的能力,同时实现了 FactoryBean 接口,当通过 getObject 方法获得 Bean 时,将得到代理类。

2.5 Target

在之前的演示代码中,我们直接为 ProxyFactory 指定一个对象为 Target。在 ProxyFactoryBean 中不仅能使用这种方式,还可以通过 TargetSource 的形式指定。

TargetSource 相当于为对象进行了一层封装,ProxyFactoryBean 将通过 TargetSource 的 getTarget 方法来获得目标对象。于是,我们可以通过 getTarget 方法来控制获得的目标对象TargetSource 的几种实现类有:

(1)SingletonTargetSource

很简单,内部只持有一个目标对象,直接返回。和我们直接指定对象的效果是一样的。

(2)PrototypeTargetSource

每次将返回一个新的目标对象实例。

(3)HotSwappableTartgetSource

运行时,根据特定条件,动态替换目标对象类的具体实现。例如当一个数据源挂了,可以切换至另外一个。

(4)CommonsPool2TargetSource

返回有限数目的目标对象实例,类似一个对象池。

(5)ThreadLocalTargetSource

为不同线程调用提供不同目标对象

2.6 Joinpoint

终于到了最后的 Joinpoint,我们通过下面的示例来理解 Joinpoint 的工作机制。

MockTask task = new MockTask();
ProxyFactory weaver = new ProxyFactory(task);
weaver.setInterfaces(new Class[]{ITask.class});
PrepareResourceBeforeAdvice beforeAdvice = new PrepareResourceBeforeAdvice();
ResourceCleanAfterReturningAdvice afterAdvice = new ResourceCleanAfterReturningAdvice();
weaver.addAdvice(beforeAdvice);
weaver.addAdvice(afterAdvice);
ITask proxyObject = (ITask) weaver.getProxy();
proxyObject.execute();/** output
准备资源
开始执行任务
任务完成
资源清理
**/

我们知道 getProxy 会通过动态代理生成一个 ITask 的接口类,那么 execute 方法的内部是如何先执行了 beforeAdvice 的 before 方法,接着执行 task 的 execute方法,再执行 afterAdvice 的 after 方法呢?

答案就在生成的代理类中。在动态代理中,代理类方法调用的逻辑由 InvocationHandler 实例的 invoke 方法决定,那答案进一步锁定在 invoke 方法

在本示例中,ProxyFactory.getProxy  会调用  JdkDynamicAopProxy.getProxy  获取代理类。

// JdkDynamicAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());}Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

在 getProxy 中为 newProxyInstance 的 InvocationHandler 参数传入 this,即 JdkDynamicAopProxy 就是一个 InvocationHandler 的实现,其 invoke 方法如下:

// JdkDynamicAopProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 通过advised(创建对象时初始化)获得指定的advice// 会将advice用相应的MethodInterceptor封装下List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);if (chain.isEmpty()) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {// 创建一个MethodInvocationMethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// 调用procced,开始进入拦截链(执行目标对象方法和MethodInterceptor的advice)retVal = invocation.proceed();}return retVal;
}

首先获得指定的 advice,这里包含 beforeAdvice 和 afterAdvice 实例,但会用 MethodInterceptor 封装一层,为了后面的拦截链。

再创建一个 RelectiveMethodInvocation 对象,最后通过 proceed 进入拦截链。

RelectiveMethodInvocation 就是 Spring AOP 中 Joinpoint 的一个实现,其类图如下:

Joinpoint类图

首先看下 RelectiveMethodInvocation 的构造函数:

protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,@Nullable 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;}

做了些相关属性的赋值,然后看向 proceed 方法,如何调用目标对象和拦截器。

public Object proceed() throws Throwable {// currentInterceptorIndex从-1开始// 当达到已调用了所有的拦截器后,通过invokeJoinpoint调用目标对象的方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}// 获得拦截器,调用其invoke方法// currentInterceptorIndex加1Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}

currentInterceptorIndex 从 -1 开始,interceptorsAndDynamicMethodMatchers里有两个拦截器,再由于减 1,所有调用目标对象方法的条件是currentInterceptorIndex 等于 1。

首先由于 -1 != 1,会获得包含了 beforeAdvice 的 MethodBeforeAdviceInterceptor 实例, currentInterceptorIndex 加 1 变为 0。调用其 invoke 方法,由于是 Before-Advice,所以先执行 beforeAdvice 的 before 方法,然后调用 proceed 进入拦截链的下一环。

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

又回到了 proceed 方法,0 != 1,再次获得 advice,这次获得的是包含 afterAdvice 的 AfterReturningAdviceInterceptor实例, currentInterceptorIndex 加 1 变为 1。调用其 invoke 方法,由于是 After-Returning-Adivce,所以会先执行 proceed 进入拦截链的下一环。

// AfterReturningAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;
}

再次来到 proceed 方法,1 == 1,已调用完所有的拦截器,将执行目标对象的方法。然后 return 返回,回到 invoke 中,调用 afterAdvice 的 afterReturning

所以在 Joinpoint 的实现中,通过 MethodInterceptor 完成了 目标对象方法和 Advice 的先后执行。

小结

在了解了 Spring AOP 的实现后,笔者对 AOP 的概念更加清晰了。在学习过程中最令笔者感兴趣的是 Joinpoint 的拦截链,一开始不知道是怎么实现的,觉得很神奇 ???? 。最后学完了,总结下,好像也很简单,通过拦截器的 invoke 方法和MethodInvocation.proceed 方法(进入下一个拦截器)的相互调用。

推荐阅读

  • 后端程序员必备:书写高质量SQL的30条建议

  • 蚂蚁金服高要求的领域建模能力,对研发来说到底指什么?

  • Redis 6.0 新特性:多线程连环 13 问!

  • AI 修复 100 年前晚清影像喜提热搜,有穿越内味儿了!

  • 你现在从事的程序员还有多久会消失?牛津大学研究员帮你算了算

  • 一次对语音技术的彻底批判

  • 到底是哪些人在玩链游?| 《区块链游戏玩家研究报告》

真香,朕在看了!

关于Spring AOP,除了动态代理、CGLIB,你还知道什么?相关推荐

  1. spring—AOP 的动态代理技术

    AOP 的动态代理技术 常用的动态代理技术 JDK 代理 : 基于接口的动态代理技术 cglib 代理:基于父类的动态代理技术 JDK 代理 public class proxy {@Testpubl ...

  2. SpringBoot/Spring AOP默认动态代理方式

    Spring 5.x中AOP默认依旧使用JDK动态代理 SpringBoot 2.x开始,AOP为了解决使用JDK动态代理可能导致的类型转换异常,而使用CGLIB. 在SpringBoot 2.x中, ...

  3. Spring : Spring Aop JDK动态代理调用过程

    1.美图 2.概述 JDK动态代理参考 : JDK动态代理 3.源码 打开JdkDynamicAopProxy类,查看invoke方法: /*** Implementation of {@code I ...

  4. Spring AOP JDK动态代理报错:class com.sun.proxy.$Proxy0 cannot be cast to class com.aha.Spring5.jdkproxy.

    报错时候的书写 public class JDKProxy {public static void main(String[] args) {UserDaoImpl userDao = new Use ...

  5. Spring 初识Aop JDK动态代理实现 原理初显

    Spring 初识Aop JDK动态代理实现 原理初显 一.项目结构 二.具体步骤: 1.创建maven项目 创建好包结构 2.写一个TestDao接口 及实现类 3. 写一个自己的切面类 4.jav ...

  6. spring的aop的动态代理机制都有哪些_Spring学习(4):Spring AOP

    Spring AOP说明 AOP(Aspect Oriented Pragraming)面向切面编程,AOP采用横向抽取机制,取代了传统纵向继承体系的重复性代码(性能监视.事务管理.安全检查.缓存). ...

  7. 浅谈Spring中JDK动态代理与CGLIB动态代理

    前言 Spring是Java程序员基本不可能绕开的一个框架,它的核心思想是IOC(控制反转)和AOP(面向切面编程).在Spring中这两个核心思想都是基于设计模式实现的,IOC思想的实现基于工厂模式 ...

  8. AOP、动态代理、CGlib(原理实践)

    Java 代理模式实现方式,主要有如下五种方法: 1. 静态代理,工程师编辑代理类代码,实现代理模式:在编译期就生成了代理类. 2. 基于 JDK 实现动态代理,通过jdk提供的工具方法Proxy.n ...

  9. (Spring)静态/动态代理模式(AOP底层)

    文章目录 1.静态代理 2.动态代理 1.静态代理 静态代理角色分析 抽象角色 : 一般使用接口或者抽象类来实现 真实角色 : 被代理的角色 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会 ...

  10. 【Spring AOP】静态代理设计模式、Spring 动态代理开发详解、切入点详解(切入点表达式、切入点函数)

    AOP 编程 静态代理设计模式 1. 为什么需要代理设计模式 2. 代理设计模式 名词解释 代理开发的核心要素 静态代理编码 静态代理存在的问题 Spring 动态代理开发 搭建开发环境 Spring ...

最新文章

  1. 关于 linux io_uring 性能测试 及其 实现原理的一些探索
  2. document.all.item的解释和一个表单向多页面提交
  3. 线上操作与线上问题排查实战
  4. SpringBoot使用SOFA-Lookout监控
  5. python语法问题
  6. 联邦知识蒸馏概述与思考(续)
  7. Spring注解 @Async 实现异步调用方法
  8. 电商促销惊喜海报设计模板,会讲故事的素材
  9. 8.5 输入输出重定向
  10. win10cmd计算机管理界面,Win10命令提示符cmd在哪 Win10以管理员身份运行方法
  11. 使用 wpa_supplicant 连接 WiFi
  12. Gmail使用POP3设置的奥秘
  13. 云终端计算机进入bios,【惠普进bios按什么键】惠普进bios调u盘启动_惠普进入bios-系统城...
  14. 学霸,顾名思义,就是成绩非常好
  15. 使用git将远程仓库和本地仓库关联
  16. 求和:1/3+3/5+5/7+7/9+………..+97/99
  17. 转载:国学与古代文学的关系
  18. 如何实现复制微信图文到Word文档
  19. PostgreSQL-Vacuum
  20. 安利这几个真人配音软件

热门文章

  1. C++ STL 容器 vector
  2. java进程内存一直没释放_五分钟彻底搞懂你一直没明白的Linux内存管理
  3. python贪心算法求删数问题_贪心算法删数问题
  4. python 知乎 合并 pdf_一键下载:将知乎专栏导出成电子书
  5. python 三维散点图拟合曲面_python实现三维拟合的方法
  6. 总有一些人在祖国需要的时候挺身而出
  7. 中国已消失的9所世界级大学
  8. AI产品经理必修课:机器学习算法
  9. 他受他爸影响,他爸受数学家影响,最终造出了自动旋转的房子!
  10. 自注意力机制Self-attention(1)