1

在我的简单项目中添加 AOP 功能时出现以下错误,有人可以帮我解释一下吗?我还在下面提到了代码的相关部分。

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.AOP.Car' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:346)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:337)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123)
    at com.AOP.App.main(App.java:13)

package com.AOP;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;    
@Configuration
@ComponentScan(basePackages = "com.AOP")
public class AppConfig {        
}

package com.AOP;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App 
{
    public static void main( String[] args )
    {
        ApplicationContext context = new  AnnotationConfigApplicationContext(AppConfig.class);
        Car car =  context.getBean(Car.class);      
        car.drive();
    }
}

package com.AOP;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Car implements Vehicle{

    @Autowired
    private Tyre tyre;      
    public Tyre getTyre() {
        return tyre;
    }

    public void setTyre(Tyre tyre) {
        this.tyre = tyre;
    }

    public void drive()
    {
        System.out.println("driving a car");
        System.out.println(tyre);
    }
}

package com.AOP;

public interface Vehicle {
    void drive();

}

package com.AOP;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Component
@Aspect
@EnableAspectJAutoProxy
public class AOPClass {

    @After("execution(* setT*(..))")    
    public void afterAdvice2()
    {
        System.out.println("After Advise (set) start here");
    }

    @Before("execution(* drive(..))")   
    public void beforeAdvice1()
    {
        System.out.println("Before Advise (drive) start here");
    }
}

如果我在没有实现“车辆”接口的情况下获得一个简单的“汽车”类,那么一切正常。但是添加该扩展名会导致menterror。

4

1 回答 1

1

这种行为在Spring 文档中有很好的描述。你的情况正是:

如果要代理的目标对象实现了至少一个接口,则使用 JDK 动态代理。

您仍然可以通过名称获取 bean,并查看它的类是什么:

    Object b = context.getBean("car");      
    System.out.println(b.getClass().getName());

它将类似于com.sun.proxy.$Proxy38,如果您尝试浏览其界面,其中会有com.AOP.Vehicle

至此,就很清楚为什么不能按类获取bean了。

该怎么办 ?有一些选项:

  • 使Car不实现Vehicle(任何接口)。这样,bean 将被 CGLIB 代理(并且它的类保持不变),并且您的代码将工作
  • 通过将以下属性添加到 annotation 来强制在任何地方使用 CGLIB 代理@EnableAspectJAutoProxy(proxyTargetClass=true)。您的代码将起作用
  • 通过名称获取 bean(参见上面的代码)
  • 通过接口获取 bean:
    Vehicle car =  context.getBean(Vehicle.class);      
    car.drive();
于 2019-07-14T08:05:50.987 回答