Michel Jung
Michel Jung

Reputation: 3296

Constructor-Injected field is null in Spring CGLIB enhanced bean

I have this repository:

@Repository
public class MyRepository {

  private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;

  public MyRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
    this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
  }

  void doSomething() {
    namedParameterJdbcTemplate.update(...);
  }
}

Which worked as expected with Spring Boot 1.4.5 (Spring Core & JDBC 4.3.7). When debugging doSomething(), I can see that the instance of MyRepository is an ordinary object and the namedParameterJdbcTemplate is set.

However, as soon as I update to Spring Boot 1.4.6 (Spring Core & JDBC 4.3.8) or higher, the instance of MyRepository is a MyRepository$$EnhancerBySpringCGLIB and namedParameterJdbcTemplate is null. I see it being injected in the constructor, however, at that point my repository is not yet CGLIB enhanced.

Why is that? I couldn't find a hint in the release 4.3.8 release notes.

Upvotes: 4

Views: 2625

Answers (4)

Sander Ruul
Sander Ruul

Reputation: 51

I had a similar problem... I fixed my case by changing method to public instead of protected.

Have you tried

@Repository
public class MyRepository {

  private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;

  public MyRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
    this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
  }

  public void doSomething() {
    namedParameterJdbcTemplate.update(...);
  }
}

Upvotes: 4

extreme2048
extreme2048

Reputation: 1

// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.

if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {

  /* 
    We can skip creating a MethodInvocation: just invoke the target directly.
    Note that the final invoker must be an InvokerInterceptor, so we know
    it does nothing but a reflective operation on the target and no hot
    swapping or fancy proxying.
  */
  Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
  retVal = methodProxy.invoke(target, argsToUse);

} else {

  // We need to create a method invocation.
  retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}

Upvotes: 0

Felipe Desiderati
Felipe Desiderati

Reputation: 3002

I had something related. My methods were final and because of this, Spring was using CGLIB Proxied Classes instead of the default behavior (Spring AOP Proxied Classes). So to access the class properties, I had to call the getXXX() method, otherwise, the property would be returned null every time I've tried to access it.

Upvotes: 5

Michel Jung
Michel Jung

Reputation: 3296

Even though I couldn't reproduce it in a minimal example, my bug report got accepted.

Upvotes: 1

Related Questions