gpt4 book ai didi

java - NoSuchBeanDefinitionException 导致 beans 接口(interface)或 bean 上的建议

转载 作者:行者123 更新时间:2023-11-30 10:26:43 26 4
gpt4 key购买 nike

学习 Spring,遇到了一些我无法弄清楚或找不到任何引用的东西。制作了一个简约的项目来过滤掉困惑并使事情更清晰:1 个包 6 个文件,不包括 pom.xml :

1 App.java - 里面是 main() 方法。

package beantest;

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

public class App{
public static void main(String[] args){

ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);

ClassAAA aaa = (ClassAAA) context.getBean(ClassAAA.class);
ClassBBB bbb = (ClassBBB) context.getBean(ClassBBB.class);

aaa.doSomething();
bbb.doSomething();
}
}

2 ClassAAA.java

package beantest;

public class ClassAAA{
public void doSomething(){
System.out.println("running 'doSomething()' by AAA object");
}
}

3 ClassBBB.java - ClassAAA 和 ClassBBB 之间的唯一区别是 BBB 实现了 InterfaceX。

package beantest;

public class ClassBBB implements InterfaceX{
public void doSomething(){
System.out.println("running 'doSomething()' by BBB object");
}
}

4 InterfaceX.java - 没有方法,处于这种状态。

package beantest;

public interface InterfaceX{
//void doSomething();
}

5 JavaConfig.java

package beantest;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class JavaConfig{

@Bean
public ClassAAA aaa(){
return new ClassAAA();
}

@Bean
public ClassBBB bbb(){
return new ClassBBB();
}

@Bean
public Aspect1 aspect1(){
return new Aspect1();
}
}

6 看点1.java

package beantest;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class Aspect1{

@Before ("execution(* beantest.ClassAAA.doSomething(..))")
public void beforeAAAdoesSomething(){
System.out.println("##### BEFORE advice on AAA's doSomething() #####");
}

@Before ("execution(* beantest.ClassBBB.doSomething(..))")
public void beforeBBBdoesSomething(){
System.out.println("##### BEFORE advice on BBB's doSomething() #####");
}
}

*** 运行它会得到预期的输出:

##### BEFORE advice on AAA's doSomething() #####
running 'doSomething()' by AAA object
##### BEFORE advice on BBB's doSomething() #####
running 'doSomething()' by BBB object

*** 取消注释 InterfaceX.java 中的“doSomething”方法并运行会得到以下输出:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'beantest.ClassBBB' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1093)
at beantest.App.main(App.java:12)

为什么在从未在任何地方提及所述接口(interface)时运行作为接口(interface)实现的方法会阻止 Spring 找到 bean?

如果从这里我要注释掉 Aspect1.java 中关于 ClassBBB 的建议

//@Before ("execution(* beantest.ClassBBB.doSomething(..))")

没有抛出异常,输出符合预期:

##### BEFORE advice on AAA's doSomething() #####
running 'doSomething()' by AAA object
running 'doSomething()' by BBB object

最后,改变

ClassBBB bbb = (ClassBBB) context.getBean(ClassBBB.class);

InterfaceX bbb = (InterfaceX) context.getBean(InterfaceX.class);

通过未注释的建议和接口(interface)方法解决了问题。

我什么时候应该按类查找实现接口(interface)的 bean?我在实验时无意中发现了这个东西。

提前致谢。

最佳答案

发件人:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-proxying

Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given target object. (JDK dynamic proxies are preferred whenever you have a choice).

If the target object to be proxied implements at least one interface then a JDK dynamic proxy will be used. All of the interfaces implemented by the target type will be proxied. If the target object does not implement any interfaces then a CGLIB proxy will be created.

所以基本上,如果您的类有一个接口(interface),spring 将通过该接口(interface)代理它,因此要正确执行通知,您必须通过接口(interface)引用该 bean。如果没有接口(interface),它将为实际类创建一个 CGLIB 代理,您可以按类引用该 bean。

您可以通过设置覆盖此默认行为并强制使用 CGLIB 代理和基于类的建议:@EnableAspectJAutoProxy(proxyTargetClass=true)

其中的 javadoc 指出:“指示是否要创建基于子类 (CGLIB) 的代理,而不是基于标准 Java 接口(interface)的代理。”

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/EnableAspectJAutoProxy.html

关于java - NoSuchBeanDefinitionException 导致 beans 接口(interface)或 bean 上的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45579173/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com