Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java @可缓存中断依赖注入_Java_Spring_Dependency Injection_Annotations_Proxy Classes - Fatal编程技术网

Java @可缓存中断依赖注入

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

我偶然发现了一个案例,使用@Cacheable创建的AOP代理破坏了Spring 3.1.1中的依赖注入。以下是我的设想:

我有一个接口和一个类,在实现的方法中使用@Cacheable实现这个接口

接口示例:

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语句。