java 不是的 Spring AOP 代理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/305263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The Spring AOP Proxy that isn't
提问by MikeHoss
I have two Spring proxies set up:
我设置了两个 Spring 代理:
<bean id="simpleBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="simpleBeanTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>cacheInterceptor</value>
</list>
</property>
</bean>
<bean id="springDao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="springDaoTarget"/>
<property name="interceptorNames">
<list>
<value>daoInterceptor</value>
</list>
</property>
</bean>
simpleBean works just fine -- springDao does not.
simpleBean 工作得很好—— springDao 没有。
The SpringDao class looks like:
SpringDao 类看起来像:
public class SpringDao extends JdbcDaoSupport {
private SimpleJdbcTemplate simpleJdbcTemplate;
public SimpleJdbcTemplate getSimpleJdbcTemplate() {
if (simpleJdbcTemplate==null) {
simpleJdbcTemplate= new SimpleJdbcTemplate(getDataSource());
}
return simpleJdbcTemplate;
}
...
And I have my unit test autowired like this:
我的单元测试像这样自动连接:
@Autowired
@Qualifier("springDao")
protected SpringDao springDao;
And the first indication something is wrong is I get this error:
出现问题的第一个迹象是我收到此错误:
Could not autowire field: . . . nested exception is java.lang.IllegalArgumentException
无法自动装配字段:。. . 嵌套异常是 java.lang.IllegalArgumentException
If I comment out the @Qualifier annotation and run my unit test again, I get this:
如果我注释掉 @Qualifier 注释并再次运行我的单元测试,我会得到:
No unique bean of type ... expected single matching bean but found 2: [springDaoTarget, springDao]
没有类型的唯一 bean ... 预期单个匹配 bean,但发现 2: [springDaoTarget, springDao]
That is what I expected.
这正是我所期望的。
So I changed my autowiring to
所以我改变了我的自动装配
@Autowired
@Qualifier("springDaoTarget")
protected SpringCustomerCapacityDao springDao;
And added the following to my unit test:
并将以下内容添加到我的单元测试中:
Object proxy = applicationContext.getBean("springDao");
Assert.assertNotNull(proxy);
Assert.assertTrue(proxy instanceof SpringDao);
And the instanceof test failed, which (to me) means that my proxy is not really my proxy.
并且 instanceof 测试失败了,这(对我而言)意味着我的代理并不是真正的代理。
So I'm confused. What's going on? How can I fix this?
所以我很困惑。这是怎么回事?我怎样才能解决这个问题?
EditHere is the requested springDaoTarget definition, which will disappoint many people:
编辑这里是请求的 springDaoTarget 定义,这会让很多人失望:
<bean id="springDaoTarget" class="com.company.SpringDao">
回答by cliff.meyers
If the target of your proxy implements at least one interface then Spring's default behavior is to create a JDK Proxy that implements all the interfaces of the target. This means it will not be a subclass of the target class. You can override this by forcing the creation of CGLIB proxies instead which are dynamic subclasses of the target.
如果代理的目标至少实现了一个接口,那么 Spring 的默认行为是创建一个实现目标所有接口的 JDK 代理。这意味着它不会是目标类的子类。您可以通过强制创建 CGLIB 代理而不是目标的动态子类来覆盖它。
As a general rule, if you are going to use AOP but only use interfaces in a limited fashion you'll want to force CGLIB. Otherwise you will have lots of JDK Proxies in your container which are not of the same type as the bean implementations you loaded.
作为一般规则,如果您打算使用 AOP 但仅以有限的方式使用接口,您将需要强制使用 CGLIB。否则,您的容器中将有很多 JDK 代理,它们与您加载的 bean 实现的类型不同。
See Cliff Meyers blog: Spring AOP: CGLIB or JDK Dynamic Proxies?
请参阅 Cliff Meyers 博客:Spring AOP:CGLIB 或 JDK 动态代理?
回答by MikeHoss
It was easy to fix, once I figured it out. SpringDao no longer inherits from JdbcDaoSupport and now it works.
一旦我想通了,就很容易修复。SpringDao 不再继承自 JdbcDaoSupport,现在它可以工作了。

