Java @可缓存中断依赖注入
我偶然发现了一个案例,使用@Cacheable创建的AOP代理破坏了Spring 3.1.1中的依赖注入。以下是我的设想: 我有一个接口和一个类,在实现的方法中使用@Cacheable实现这个接口 接口示例:Java @可缓存中断依赖注入,java,spring,dependency-injection,annotations,proxy-classes,Java,Spring,Dependency Injection,Annotations,Proxy Classes,我偶然发现了一个案例,使用@Cacheable创建的AOP代理破坏了Spring 3.1.1中的依赖注入。以下是我的设想: 我有一个接口和一个类,在实现的方法中使用@Cacheable实现这个接口 接口示例: public interface ImgService { public byte[] getImage(String name); } 实施示例: public class ImgServiceImpl implements ImgService { @Cacheab
public interface ImgService {
public byte[] getImage(String name);
}
实施示例:
public class ImgServiceImpl implements ImgService {
@Cacheable(cacheName = "someCache")
public byte[] getImage(String name){//TODO};
protected String someOtherMethod(){//};
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" })
public class ImgServiceTest {
@Inject
private ImgService;
}
我还需要JUnit测试类—一个注入接口,另一个注入实现:
public class ImgServiceImpl implements ImgService {
@Cacheable(cacheName = "someCache")
public byte[] getImage(String name){//TODO};
protected String someOtherMethod(){//};
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:META-INF/spring.xml" })
public class ImgServiceTest {
@Inject
private ImgService;
}
及
接口的依赖项注入工作正常。然而,当我在第二个测试类中注入实现时,我得到了一个“自动连接依赖项的注入失败”。我能够对其进行调试,但ClassUtils.isAssignableValue()似乎错误地将所需类型与代理类进行了比较。它由DefaultListableBeanFactory调用。更奇怪的是,如果我从实现的方法中删除@Cacheable注释,并将其添加到其他受保护/私有方法中,依赖项注入就会再次正常工作。这是一个bug吗?处理这种情况的正确方法是什么?这不是bug,而是使用JDK动态代理实现AOP的预期副作用 由于对
ImgServiceImpl
的可缓存方法的所有调用都应通过ImgService
类型的动态代理,因此无法将此依赖关系注入ImgServiceImpl
类型的字段
当您将@Cacheable
移动到private
或protected
方法时,注入可以工作,因为@Cacheable
在这种情况下不生效-只有public
方法可以使用基于代理的AOP进行通知
因此,您应该将要注入的字段声明为ImgService
,或者将Spring配置为使用基于目标类的代理,而不是使用proxy target class=“true”
另一种选择是配置Spring以供使用(需要编译时或加载时编织)
它适用于Spring提供的所有基于AOP的特性(事务、安全性、异步执行、缓存、自定义方面等)
另请参见:
- 好的,这是我最后提出的解决方案。我实现了一个简单的方法,该方法尝试根据
org.springframework.aop.framework.Advised
类的实现从代理中提取目标对象:
@SuppressWarnings({"unchecked"})
public static <T> T getTargetObject(Object proxy, Class<T> targetClass) {
if (AopUtils.isJdkDynamicProxy(proxy)) {
try {
return (T) ((Advised)proxy).getTargetSource().getTarget();
} catch (Exception e) {
return null;
}
} else {
return (T) proxy;
}
}
这里还有一个很好的参考资料-谢谢你的回答。对我来说,ClassUtils方法不处理这个问题仍然很奇怪,因为它似乎只需要一个if语句。