为什么代理不用于自动装配

时间:2013-09-25 02:39:22

标签: spring proxy-classes

我找不到为什么每个自动装配的bean都没有被代理自动装配的原因。我知道因为@Transactional注释不起作用,我在eclipse调试期间检查了自动装配的组件。当然,每个组件都实现了一些接口,我使用与接口相关的@Autowired注释。 我只有一个配置aop:

<tx:annotation-driven transaction-manager="transactionManager" />

我将JPA与hibernate,spring-mvc,spring-webflow,spring-security和spring-data一起使用。扩展org.springframework.data.repository.CrudRepository的接口由代理自动装配。但我的组件不是。例如,我有一个实现MyClass的课程MyInterface

@Service
public class MyClass implements MyInterface {
@Autowired
MyCrudReposiotry reposiotry;
....
}

如果我在某处自动装配MyInterface:

@Autowired
MyInterface mi;

然后mi只是对MyClass对象的引用,存储库是对代理org.springframework.aop.framework.JdkDynamicAopProxy的引用。非常有趣的是,在测试中mi是对代理的引用。我的测试上下文不包含web-flow和mvc配置。

也许我应该检查一些间接的aop配置。什么可以通过代理关闭自动装配?

2 个答案:

答案 0 :(得分:6)

我的猜测是你要扫描两次相同的组件。您可能在根上下文中(对于ContextLoaderListener)和一个用于DispatcherServlet。如果两者扫描相同的类,则最后是重复的(以及一个代理和一个非代理实例)。

答案 1 :(得分:4)

代理和自动布线彼此独立。当您使用@AutoWired时,它会找到另一个实现所需接口并注入它的bean。它找到的bean实例可能是普通对象或代理 - 它与Autowired无关。

弹簧会自动为某些bean创建代理。正如您已经注意到,当您使用@Transactional时会出现这种情况。当spring容器实例化具有@Transactional注释的bean时,对象将被包装在代理中。实际对象在上下文中由代理替换。这样做是为了使spring能够拦截对这些方法的调用,并在方法调用之前和之后添加begin / commit事务调用。这是由spring-aop模块实现的。任何依赖AOP(@Transactional@Secured)的功能都将导致代理的创建。

使用代理的另一种情况是动态创建实现。如果是CRUDRepository,则只需要实现该接口。使用相同的代理基础架构即时创建它的实现。