Home > Blockchain >  Spring ProxyFactoryBean @Autowired not working
Spring ProxyFactoryBean @Autowired not working

Time:12-23

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.

testProxyFactoryBean is Autowiring to testServiceImpl instead of testProxyFactoryBean

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! ;)

  • Related