没有可用的 'concert.PerformanceImp' 类型的合格 bean
No qualifying bean of type 'concert.PerformanceImp' available
我仍然是 Spring Framework 的初学者,所以我尝试在 Spring AOP 中编写一个关于 "introduction" 的程序,但我在编译时遇到错误。请在 concert
:
包中找到下面的 classes
PerformanceImp.java
package concert;
import org.springframework.stereotype.Component;
@Component
public class PerformanceImp implements Performance {
public void perform() {
System.out.println("This is the performance function");
}
}
Performance.java
package concert;
public interface Performance {
public void perform();
}
Encoreable.java
package concert;
public interface Encoreable {
void performEncore();
}
DefaultEncoreable.java
package concert;
import org.springframework.stereotype.Component;
@Component
public class DefaultEncoreable implements Encoreable {
public void performEncore() {
System.out.println("This is the performEncore function");
}
}
EncoreableIntroducer.java
package concert;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class EncoreableIntroducer {
@DeclareParents(value="concert.Performance+",
defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
ConcertConfig.java
package concert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("concert")
public class ConcertConfig {
}
主要 class:
Main.java
package concert;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ConcertConfig.class);
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
((Encoreable) pi).performEncore();
pi.perform();
}
}
我收到错误:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'concert.PerformanceImp' available
有什么帮助吗?
尝试:
Performance pi = context.getBean("performanceImp", Performance.class);
而不是:
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
默认情况下您无法访问实现 (PerformanceImp
),因为您启用了 AOP,它设置为目标接口而不是实现。如果您删除 EnableAspectJAutoProxy
,您会发现代码可以正常工作。
要进一步了解 AOP 定位的工作原理,请查看此 Spring Documentation
Spring AOP can also use CGLIB proxies. This is necessary to proxy
classes rather than interfaces. CGLIB is used by default if a business
object does not implement an interface. As it is good practice to
program to interfaces rather than classes; business classes normally
will implement one or more business interfaces. It is possible to
force the use of CGLIB, in those (hopefully rare) cases where you need
to advise a method that is not declared on an interface, or where you
need to pass a proxied object to a method as a concrete type.
所以你有两个选择:
- 尝试从
ApplicationContext
获取bean时获取接口。
- 启用 AOP 以具体 类 为目标。
要执行第 2 点,请按如下方式修改注释:
@EnableAspectJAutoProxy(proxyTargetClass = true)
我仍然是 Spring Framework 的初学者,所以我尝试在 Spring AOP 中编写一个关于 "introduction" 的程序,但我在编译时遇到错误。请在 concert
:
PerformanceImp.java
package concert;
import org.springframework.stereotype.Component;
@Component
public class PerformanceImp implements Performance {
public void perform() {
System.out.println("This is the performance function");
}
}
Performance.java
package concert;
public interface Performance {
public void perform();
}
Encoreable.java
package concert;
public interface Encoreable {
void performEncore();
}
DefaultEncoreable.java
package concert;
import org.springframework.stereotype.Component;
@Component
public class DefaultEncoreable implements Encoreable {
public void performEncore() {
System.out.println("This is the performEncore function");
}
}
EncoreableIntroducer.java
package concert;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class EncoreableIntroducer {
@DeclareParents(value="concert.Performance+",
defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
ConcertConfig.java
package concert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("concert")
public class ConcertConfig {
}
主要 class:
Main.java
package concert;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ConcertConfig.class);
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
((Encoreable) pi).performEncore();
pi.perform();
}
}
我收到错误:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'concert.PerformanceImp' available
有什么帮助吗?
尝试:
Performance pi = context.getBean("performanceImp", Performance.class);
而不是:
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
默认情况下您无法访问实现 (PerformanceImp
),因为您启用了 AOP,它设置为目标接口而不是实现。如果您删除 EnableAspectJAutoProxy
,您会发现代码可以正常工作。
要进一步了解 AOP 定位的工作原理,请查看此 Spring Documentation
Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather than interfaces. CGLIB is used by default if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes; business classes normally will implement one or more business interfaces. It is possible to force the use of CGLIB, in those (hopefully rare) cases where you need to advise a method that is not declared on an interface, or where you need to pass a proxied object to a method as a concrete type.
所以你有两个选择:
- 尝试从
ApplicationContext
获取bean时获取接口。 - 启用 AOP 以具体 类 为目标。
要执行第 2 点,请按如下方式修改注释:
@EnableAspectJAutoProxy(proxyTargetClass = true)