Java – @ cacheable breaks dependency injection

I stumbled upon a case in which the AOP proxy created with @ cacheable was created in spring 3.1 Dependency injection is broken in 1 This is my scene:

I have an interface and a class that implements this interface using @ cacheable in the implemented method

Sample interface:

public interface ImgService {
    public byte[] getImage(String name);
}

Example implementation:

public class ImgServiceImpl implements ImgService {

    @Cacheable(cacheName = "someCache")
    public byte[] getImage(String name){//TODO};

    protected String someOtherMethod(){//};
}

I also need JUnit test classes - one injection interface and another injection implementation:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:Meta-INF/spring.xml" })
public class ImgServiceTest {

    @Inject
    private ImgService;
}

and

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:Meta-INF/spring.xml" })
public class ImgServiceImpltest {

    @Inject
    private ImgServiceImpl;
}

Dependency injection of the interface works normally However, when I injected the implementation in the second test class, I got "failed to inject automatically connected dependencies" I can debug it. It looks like classutils Isassignablevalue() incorrectly compares the required type with the proxy class It is called by defaultlistablebeanfactory More strangely, if I remove the @ cacheable annotation from the implemented method and add it to some other protected / private methods, dependency injection works again This is a mistake. What is the correct way to deal with this situation?

Solution

This is not an error, it is the expected side effect of AOP implementation using JDK dynamic proxy

Since all calls to cacheable methods of imgserviceimpl should pass through a dynamic proxy of type imgservice, this dependency cannot be injected into fields of type imgserviceimpl

When you move @ cacheable to private or protected methods, the injection is valid because @ cacheable will not take effect in this case - only proxy based AOP recommended public methods can be used

Therefore, you should declare the fields to be injected as imgservice, or use proxy target class = "true" to configure spring to use a proxy based on the target class

Another option is to configure spring to use AspectJ based AOP implementation (requires compilation or load time weaving)

It is applicable to all AOP based functions provided by spring (transaction, security, asynchronous execution, caching, customization, etc.)

You can also see:

> 7.6 Proxying mechanisms

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>