当我还有一个针对 Spring 中的 bean 的方面时,为什么不可能有一个通用 bean?
Why is it not possible to have a generic bean when i have also an Aspect targeting the bean in Spring?
您好,关于 Spring 方面,我有一个相当具体的问题让我感到困惑。我尝试了 Springs 和 Apsects,并尝试了一个非常简单的例子来了解它是如何工作的:
@Component
public class Comment {
private String text;
private String author;
public String get() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
@Aspect
public class LoggingAspect {
@Around("execution(* aop.beans.*.*(..))")
public void log(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Start Aspect for method: " + joinPoint.getSignature());
joinPoint.proceed();
}
}
我的配置文件:
@Configuration
@ComponentScan("aop.beans")
@EnableAspectJAutoProxy
public class ProjectConfig {
@Bean
public LoggingAspect aspect() {
return new LoggingAspect();
}
}
然后我使用了一个简单的 Main 方法来稍微尝试一下这个概念:
public class Main {
public static void main(String[] args) {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProjectConfig.class);
context.registerShutdownHook();
CommentService service = context.getBean(CommentService.class);
Comment comment = context.getBean(Comment.class);
comment.setAuthor("Andreas");
comment.setText("Hallo.");
service.publishComment(comment);
System.out.println(service.getClass());
}
}
这工作正常,但当我更改评论的层次结构时会发生一些奇怪的事情 class。我想看看如果 class 实现通用接口会发生什么,所以我将其更改如下
public class Comment implements Supplier<String>
我立即收到以下堆栈跟踪错误:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'aop.beans.Comment' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at aop.Main.main(Main.java:17)
这让我想知道这是为什么?如果我删除通用超级接口或方面 bean everthing 工作正常,但两者一起似乎不太好。有人可以提供解释吗?如果 class 有通用的 superclass,Spring 是否无法创建 Proxy 对象?
编辑:解决方案在评论中 :) 我在 Spring Proxy Mechanism Documentation
中找到了有关该机制的更多文档
发生这种情况是因为 Spring 实现 AOP 的方式。
当代理 class(在您的情况下为 Comment
)未实现任何接口时,将使用 CGLib 代理。基本上,它生成一个 class,它是代理 class 的子 class。因此,您可以通过 parent 的 class.
getBean
当有实现的接口时,Spring使用JDK动态代理,它不扩展代理class,而是实现它的所有接口,因此你找不到bean 是 class.
这就是为什么通过接口而不是 class 自动装配 bean 始终是一个好习惯的原因。
解决方案
- 您可以通过注释配置 class
@EnableAspectJAutoProxy(proxyTargetClass = true)
. 强制 Spring 使用 AspectJ 的 CGLib 代理
- 如果您想使用 JDK 动态代理,请为
Comment
创建接口,然后使用 context.getBean(YourInterfaceName.class)
。
您好,关于 Spring 方面,我有一个相当具体的问题让我感到困惑。我尝试了 Springs 和 Apsects,并尝试了一个非常简单的例子来了解它是如何工作的:
@Component
public class Comment {
private String text;
private String author;
public String get() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
@Aspect
public class LoggingAspect {
@Around("execution(* aop.beans.*.*(..))")
public void log(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Start Aspect for method: " + joinPoint.getSignature());
joinPoint.proceed();
}
}
我的配置文件:
@Configuration
@ComponentScan("aop.beans")
@EnableAspectJAutoProxy
public class ProjectConfig {
@Bean
public LoggingAspect aspect() {
return new LoggingAspect();
}
}
然后我使用了一个简单的 Main 方法来稍微尝试一下这个概念:
public class Main {
public static void main(String[] args) {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProjectConfig.class);
context.registerShutdownHook();
CommentService service = context.getBean(CommentService.class);
Comment comment = context.getBean(Comment.class);
comment.setAuthor("Andreas");
comment.setText("Hallo.");
service.publishComment(comment);
System.out.println(service.getClass());
}
}
这工作正常,但当我更改评论的层次结构时会发生一些奇怪的事情 class。我想看看如果 class 实现通用接口会发生什么,所以我将其更改如下
public class Comment implements Supplier<String>
我立即收到以下堆栈跟踪错误:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'aop.beans.Comment' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at aop.Main.main(Main.java:17)
这让我想知道这是为什么?如果我删除通用超级接口或方面 bean everthing 工作正常,但两者一起似乎不太好。有人可以提供解释吗?如果 class 有通用的 superclass,Spring 是否无法创建 Proxy 对象?
编辑:解决方案在评论中 :) 我在 Spring Proxy Mechanism Documentation
中找到了有关该机制的更多文档发生这种情况是因为 Spring 实现 AOP 的方式。
当代理 class(在您的情况下为 Comment
)未实现任何接口时,将使用 CGLib 代理。基本上,它生成一个 class,它是代理 class 的子 class。因此,您可以通过 parent 的 class.
getBean
当有实现的接口时,Spring使用JDK动态代理,它不扩展代理class,而是实现它的所有接口,因此你找不到bean 是 class.
这就是为什么通过接口而不是 class 自动装配 bean 始终是一个好习惯的原因。
解决方案
- 您可以通过注释配置 class
@EnableAspectJAutoProxy(proxyTargetClass = true)
. 强制 Spring 使用 AspectJ 的 CGLib 代理
- 如果您想使用 JDK 动态代理,请为
Comment
创建接口,然后使用context.getBean(YourInterfaceName.class)
。