@EnableAspectJAutoProxy 停用我的 bean 定义

@EnableAspectJAutoProxy deactivate my bean definition

我在 IDEA 中设置了一个新的 Spring App(不是 spring boot),并手动下载了 aspectjweaver, 写下面的代码练习aop。

根配置class是:

@Configuration
/*@EnableAspectJAutoProxy*/
@ComponentScan
public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext();
        ctx.register(Main.class);
        ctx.refresh();
        Performance performance=ctx.getBean(WoodStock.class);
        //System.out.println(ctx.getBean(Audience.class));
        performance.performance();
     }
}

项目布局为:

+com.dawn.www
  -Main.java
  +aspect
    -Audience.java
  +music
    -Performance.java
    -WoodStock.java

我希望 Audience 成为 WoodStock 的一个方面(在 spring 中看到它的实际效果)

@Aspect
@Component
public class Audience {
    @Before("execution(* com.dawn.www.music.Performance.performance(..))")
    public void silenceCellPhones(){
        System.out.println("-----------Silencing cell phones");
    }
}

Performance 是一个简单的接口,由 WoodStock

实现
public interface Performance {
    void performance();
}

@Component
public class WoodStock implements Performance{
    @Override
    public void performance() {
        System.out.println("WoodStock Performance start,singer singing+++++");
    }
}

@ComponentScan 应该找到在应用程序上下文中定义的 WoodStockbean,但是当我 运行 它时:

   No qualifying bean of type 'com.dawn.www.music.WoodStock' available  

但是当我注释掉 @EnableAspectJAutoProxy 时,WoodStock 可以从 应用上下文?这就是为什么?

Performance performance=ctx.getBean(Performance.class); Spring Aop在不使用CGLIB时只支持接口级代理,所以不要使用class,使用接口

  1. 当您使用@EnableAspecjAutoProxy 时,spring 将自动 为所有匹配的 bean 创建代理(即通过 Audience 方面的 WoodStock)。
  2. 现在,由于您还没有使用 'proxyTargetClass=true' @EnableAspectJAutoProxy,它将返回到 JDK 代理而不是 CGLIB.
  3. JDK代理是基于接口的,因此你的代理是类型 'Performance'.
  4. 这就是您收到“没有符合条件的类型的 bean”的原因 'com.dawn.www.music.WoodStock' available' 当您尝试查找 bean 时 使用 WoodStock 类型
  5. 现在,在注释掉@EnableAspectJAutoProxy 之后,WoodStock 变成了 简单的 bean,可以通过 ctx.getBean(..)
  6. 访问
  7. 与 'proxyTargetClass=true',CGLIB 代理已启用并创建 WoodStock 类型的代理

建议

Use 'proxyTargetClass=true' with ctx.getBean(WoodStock.class)

Use 'proxyTargetClass=false' with ctx.getBean(Performance.class)