将 AOP 功能添加到 Spring 项目后没有发现符合条件的 Bean 错误
No qualifying Bean found error after adding AOP feature to a Spring project
我在向我的简单项目添加 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");
}
}
如果我得到一个简单的 class "Car" 而没有实现 "Vehicle" 接口,则一切正常。但是添加该扩展名会导致错误。
此行为在 Spring documentation 中有详细描述。
您的情况正好是:
If the target object to be proxied implements at least one interface, a JDK dynamic proxy is used.
你仍然可以通过名称获取bean,看看它是什么class:
Object b = context.getBean("car");
System.out.println(b.getClass().getName());
它会是类似com.sun.proxy.$Proxy38
的东西,如果你尝试浏览它的界面,其中会有com.AOP.Vehicle
。
至此,为什么class获取不到bean就明白了。
怎么办?有一些选项:
- 使
Car
不实现Vehicle
(任何接口)。这样,bean 将由 CGLIB 代理(并且其 class 保持不变),并且您的代码将工作
- 通过在注释
@EnableAspectJAutoProxy(proxyTargetClass=true)
中添加以下 属性 强制在所有地方使用 CGLIB-proxies。您的代码将有效
- 通过名称获取 bean(见上面的代码)
- 通过接口获取bean:
Vehicle car = context.getBean(Vehicle.class);
car.drive();
我在向我的简单项目添加 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");
}
}
如果我得到一个简单的 class "Car" 而没有实现 "Vehicle" 接口,则一切正常。但是添加该扩展名会导致错误。
此行为在 Spring documentation 中有详细描述。 您的情况正好是:
If the target object to be proxied implements at least one interface, a JDK dynamic proxy is used.
你仍然可以通过名称获取bean,看看它是什么class:
Object b = context.getBean("car");
System.out.println(b.getClass().getName());
它会是类似com.sun.proxy.$Proxy38
的东西,如果你尝试浏览它的界面,其中会有com.AOP.Vehicle
。
至此,为什么class获取不到bean就明白了。
怎么办?有一些选项:
- 使
Car
不实现Vehicle
(任何接口)。这样,bean 将由 CGLIB 代理(并且其 class 保持不变),并且您的代码将工作 - 通过在注释
@EnableAspectJAutoProxy(proxyTargetClass=true)
中添加以下 属性 强制在所有地方使用 CGLIB-proxies。您的代码将有效 - 通过名称获取 bean(见上面的代码)
- 通过接口获取bean:
Vehicle car = context.getBean(Vehicle.class);
car.drive();