【发布时间】:2017-11-06 09:56:56
【问题描述】:
spring 是在每次创建目标 bean 时创建代理对象还是仅在 Spring AOP 中第一次发生?
【问题讨论】:
标签: java spring proxy spring-aop
spring 是在每次创建目标 bean 时创建代理对象还是仅在 Spring AOP 中第一次发生?
【问题讨论】:
标签: java spring proxy spring-aop
编织是一种将目标类与方面交织在一起的技术,以便在合适的条件出现时执行建议。
AspectJ提供三种编织机制,分别是:source weaving、binary weaving、load weaving .
而 Spring AOP 仅提供 运行时编织。
源代码编织是编译过程的一部分,其中 Java 源代码 (*.java) 使用 AspectJ 编译器 (ajc) 编译成编织字节码 (*.class)。在这里,ajc 替换了 javac(Java 编译器)。
Target.java + MyAspect.java -- (compiled with ajc) --> Target.class
在二进制编织中,目标和方面源代码 (*.java) 分别编译成二进制类 (.class)。然后将二进制类与 AspectJ 编译器 (ajc) 组合在一起。
第 1 步:编译目标类
Target.java -- (compiled with javac) --> Target.class
第 2 步:编译 Aspect 类
MyAspect.java -- (compiled with javac or ajc) --> MyAspect.class
第 3 步。方面编织
Target.class + MyAspect.class -- (woven with ajc) --> Target.class
在负载编织中,二进制目标和方面类 (*.class) 在 JVM 使用 javaagent 等技术加载类期间被修改 (instrumented)。
由于 Spring 框架固有的基于代理的特性,Spring AOP 仅提供运行时编织。这意味着目标类实例在应用程序启动期间(或在运行时使用之前的任何其他时间)更改为代理。目标代理类会相应地拦截对目标方法的任何调用,以执行任何合适的建议。
Spring 是在每次创建目标 bean 时创建代理对象还是仅在 Spring AOP 中第一次发生?
假设您在名为 create 的控制器的名为 create 的方法上创建了一个切面,该控制器名为 BookController。
BookController,并创建目标类的代理。 目标类的代理只创建一次。CglibAopProxy。否则,代理的类型为 JdkDynamicAopProxy。BookController 的create 方法时,Spring 框架都会在将原始代理传递给您的切面之前将原始代理包装在一个连接点(在本例中为MethodInvocationProceedingJoinPoint)中。
Spring AOP 只支持运行时编织,这是否意味着目标代理只有在目标方法第一次被调用时才被创建?
当 Spring AOP 声明运行时,它试图区分 AspectJ 中的其他类型的编织。 Spring 运行时可能意味着 Spring 应用程序运行时的任何时间。
关于代理究竟是什么时候创建的,可以懒惰创建,也可以主动创建。在大多数情况下,目标类在 Spring 应用程序启动期间被代理。
在上面的示例中,控制器实例甚至在调用控制器上的任何方法之前,即在控制台中记录底线之前,就变成了代理。
2017-11-07 20:12:27.541 INFO 31394 --- [ main] com.basaki.Application : Started Application in 147.808 seconds (JVM running for 149.184)
【讨论】: