2

I have this odd problem with Spring AOP and I am hoping someone can shed some light on it.

I am using CGLIB proxies and when I execute the following aspect i get a null pointer:

@Aspect
@Component //i.e. Singleton
public class MyAspect {

    private static final Logger logger = LoggerFactory.getLogger(MyAspect.class);

    {

        logger.debug("new instance of MyAspect");  //Line 1
    }

    private AutowireCapableBeanFactory factory;

    @Inject
    public MyAspect(AutowireCapableBeanFactory factory) {

        if (factory ==null) {

            logger.debug("your factory is null");  //Line 2
        } else {

            logger.debug("your factory is not null");
        }
        this.factory = factory;
    }

    @AfterReturning(pointcut = "@annotation(com.domain.annotations.MyAnnotation)")
    public void doSomething() {

        if (factory ==null) {

            logger.debug("your factory is null again");  //Line 3
        }

                    // this is a request scoped bean
        MyRequest request = factory.getBean(MyRequest.class);  //Line 4



        if (request != null) {
            logger.debug("No");
            }
        else {
            logger.debug("Yes");
            }
    }
}

I am getting a NullPointerException at Line 4. I can see that the "factory" is null at Line 3 but it is not null when the instance is create at Line 2. I am also tracking the instances being created at Line 1.

This design works using interfaces (JDK dynamic proxies). Why do my instances variables become null at runtime and is there a work around to this?

phife757
  • 91
  • 6

1 Answers1

2

Long and short is that you can't use Spring's constructer based injection with Aspects. There's a good forum discussion on this topic here.

I personally use property-based injection for my aspects as suggested in the above forum. The example below allows you to inject a service into an auditing aspect. You don't need any additional XML configuration, as long as you make your aspect implement ApplicationContextAware.

@Aspect
@Component("auditAspect")
public class AuditAspect implements ApplicationContextAware {

ApplicationContext context;

public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    // do stuff with context here
}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;       
 }
Fil
  • 2,016
  • 18
  • 29
  • thanks Filip...I have tried property injections AND method injections to set this property, but it still doesnt work. something like: @Inject private AutowireCapableBeanFactory factory; – phife757 Jun 15 '11 at 15:03
  • Have you used the XML declaration above? I'm not sure if you can specify the factory-method property using only annotations. – Fil Jun 15 '11 at 15:04
  • im trying the xml version out... im having trouble getting an instance of AutowireCapableBeanFactory in the xml config using your example. most of my beans are config-ed by annotations. any examples would help. – phife757 Jun 15 '11 at 16:39
  • 1
    To me, it seems like the method cannot access its own instance variables at all. For example, I changed the aspect to be ApplicationContextAware (manually setting the property, not using injection), and I get the same results (null factory in method). Also, changing the property to a "static" variable fixes it. This is fine temporarily but to me that would be bad design. – phife757 Jun 15 '11 at 17:43
  • I'm able to get it working by implementing ApplicationContextAware, as described above. – Fil Jun 16 '11 at 11:55
  • @phife757 is right. See the accepted answer on http://stackoverflow.com/questions/9633840/spring-autowired-bean-for-aspect-aspect-is-null for an explanation – Gev Dec 09 '16 at 07:26