I need to intercept methods from a interface, and found this implementation of MethodInterceptor, which I tested on a new spring app and worked.
The problem is, I can't seem to get it working on the spring application I need it to.
@Configuration
public class TestMethodConfig {
@Autowired
private TestService testService;
@Bean
@Primary
public ProxyFactoryBean testProxyFactoryBean() {
ProxyFactoryBean testProxyFactoryBean = new ProxyFactoryBean();
testProxyFactoryBean.setTarget(testService);
testProxyFactoryBean.setInterceptorNames("testMethodInterceptor");
return testProxyFactoryBean;
}
}
@Service
public class TestServiceImpl implements TestService{
@Override
public void testMethod(String test) {
System.out.println("testService String");
}
}
public interface TestService{
void testMethod(String test);
}
@RestController
public class Controller {
@Autowired
private TestService testProxyFactoryBean;
@GetMapping(value = "/test")
public void test(){
testProxyFactoryBean.testMethod("valor");
}
}
@Component
public class TestMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before method");
System.out.println("invocation: " Arrays.toString(invocation.getArguments()));
Object retVal = invocation.proceed();
System.out.println("after method");
return retVal;
}
}
I used Spring Actuator to check the beans relations, and I found that the @Autowired TestService on Controller should be getting assigned to testProxyFactoryBean, but its getting assigned to the TestServiceImpl bean instead, so I believe there is a problem creating the proxy.
CodePudding user response:
In short
I don't know how/why it was:
on a new spring app and worked.
but:
I can't seem to get it working on the spring application I need it to.
..can probably be fixed!
Make it consistent
Or:
@Configuration
public class TestMethodConfig {
@Autowired
private TestService testService;
}
...
// !!
public class TestServiceImpl implements TestService{
@Override
public void testMethod(String test) {
System.out.println("testService String");
}
}
...
@Service // !!!
public interface TestService{
void testMethod(String test);
}
...
@RestController
public class Controller {
@Autowired
private TestService testProxyFactoryBean;
...
Or: Impl! (Use Interface and Impl consistently!)
In Detail
6.4. Using the ProxyFactoryBean to Create AOP Proxies
esp. Proxying Interfaces.
So with "least impact" (and java config), it should be:
@Configuration
public class TestMethodConfig {
// !!! Impl from component-scan (@Service), NOT interface:
@Autowired
private TestServiceImpl testServiceImpl; // or define custom, or "inline"...
@Bean
@Primary // only if you need it, better would be: distinct!
public ProxyFactoryBean testProxyFactoryBean() {
ProxyFactoryBean testProxyFactoryBean = new ProxyFactoryBean();
// !!! set proxyInterface as documented:
testProxyFactoryBean.setProxyInterface(TestService.class);
testProxyFactoryBean.setTarget(testServiceImpl);
testProxyFactoryBean.setInterceptorNames("testMethodInterceptor");
// ...
return testProxyFactoryBean;
}
}
..enjoy! ;)