每次创建目标bean时spring是否会创建代理对象,或者只是第一次在Spring AOP
中发生?
答案 0 :(得分:4)
编织是一种将目标类与方面交织在一起的技术,以便在出现合适的条件时执行建议。
AspectJ 提供三种类型的编织机制,即:源代码编织,二元编织和加载编织 。
虽然 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加载类时使用instrumented
等技术进行修改(javaagent
)。
由于Spring框架固有的基于代理的特性,Spring AOP仅提供运行时编织。这意味着在应用程序启动期间(或在运行时使用之前的任何其他时间),目标类实例将更改为代理。目标代理类相应地拦截对目标方法的任何调用,以执行任何合适的建议。
每次创建目标bean时Spring是否会创建代理对象,或者只是第一次在Spring AOP中发生?
假设您已经在名为create
的控制器名为BookController
的方法上创建了一个方面。
BookController
,并创建目标类的代理。 目标类的代理只创建一次。CglibAopProxy
。否则,代理的类型为JdkDynamicAopProxy
。create
方法BookController
时,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)