Java 在SpringAOP中,Spring是在每次创建目标bean时创建代理对象,还是只在第一次创建时创建代理对象?

Java 在SpringAOP中,Spring是在每次创建目标bean时创建代理对象,还是只在第一次创建时创建代理对象?,java,spring,proxy,spring-aop,Java,Spring,Proxy,Spring Aop,spring是在每次创建目标bean时创建代理对象,还是仅在springaop中第一次创建代理对象? 编织是一种将目标类与方面交织在一起的技术,以便在适当的条件出现时执行建议 AspectJ提供了三种类型的编织机制,即:源编织、二进制编织、和负载编织 而springaop只提供运行时编织 编织类型 1.源编织 源代码编织是编译过程的一部分,其中Java源代码(*.Java)使用AspectJ编译器(ajc)编译成编织字节码(*.class)。这里,ajc取代了javac(Java编译器) Tar

spring是在每次创建目标bean时创建代理对象,还是仅在
springaop
中第一次创建代理对象?

编织是一种将目标类方面交织在一起的技术,以便在适当的条件出现时执行建议

AspectJ提供了三种类型的编织机制,即:源编织二进制编织、和负载编织

springaop只提供运行时编织

编织类型 1.源编织 源代码编织是编译过程的一部分,其中Java源代码(
*.Java
)使用AspectJ编译器(
ajc
)编译成编织字节码(
*.class
)。这里,
ajc
取代了
javac
(Java编译器)

Target.java+MyAspect.java--(用ajc编译)-->Target.class

2.二元织造 在二进制编织中,目标和方面源代码(
*.java
)分别编译成二进制类(
.class
)。然后,二进制类与AspectJ编译器(
ajc
)组合在一起

步骤1:编译目标类

Target.java-->Target.class

步骤2:编译方面类

MyAspect.java--(用javac或ajc编译)-->MyAspect.class

第3步。方面编织

Target.class+MyAspect.class--(与ajc编织)-->Target.class

3.负荷织造 在负载编织中,二进制目标类和方面类(
*.class
)在JVM使用
javaagent
等技术加载类的过程中被修改(
插入指令)

4.运行时编织 由于Spring框架固有的基于代理的特性,Spring AOP只提供运行时编织。这意味着目标类实例在应用程序启动期间(或在使用之前的运行时的任何其他时间)更改为代理。目标代理类会相应地拦截对目标方法的任何调用,以执行任何适当的通知

问题 Spring是在每次创建目标bean时创建代理对象,还是在springaop中第一次创建代理对象

假设您已经在名为
BookController
的控制器的名为
create
的方法上创建了一个方面

  • 在应用程序启动期间,Spring框架实例化目标bean,
    BookController
    ,并创建目标类的代理目标类的代理只创建一次
  • 如果目标类未实现任何接口,则代理类型为
    CglibAopProxy
    。否则,代理类型为
    JdkDynamicAopProxy
  • 每次调用目标类的
    create
    方法
    BookController
    ,Spring框架都会在将原始代理传递到aspect之前将其包装在连接点中(
    MethodInvocationProceedJoinPoint
SpringAOP只支持运行时编织,这是否意味着只有在第一次调用目标方法时才能创建目标代理

当SpringAOP状态为runtime时,它试图在AspectJ中区分其他类型的编织。Spring运行时可以指Spring应用程序运行时的任何时间

至于何时创建代理的问题,可以延迟创建代理,也可以主动创建代理。在大多数情况下,目标类在Spring应用程序启动期间被代理

在上面的示例中,即使在调用控制器上的任何方法之前,即在控制台中记录底线之前,控制器实例也会转换为代理


2017-11-07 20:12:27.541信息31394---[main]com.basaki.Application:应用程序在147.808秒内启动(JVM运行149.184秒)

有一个疑问,您提到代理将在应用程序启动时创建,但Spring AOP只支持运行时编织,所以不应该在第一次调用目标方法时创建代理吗?更新了我的帖子。希望它能回答你的问题。