Search code examples
javaspringspring-mvcspring-bootspring-aop

Injected bean becomes null after using AOP


I am using Spring4 along with Spring Boot.

Before I tired to use AOP, my Bean(CommandService),which is used in the controller, is auto injected well, but after I tired to use AOP to collect some debug message, the bean becomes null!

Here is my Application.java

@Configuration
@EnableAutoConfiguration
@ComponentScan({"hello","wodinow.weixin.jaskey"})
public class Application extends  {

public static void main(String[] args) {
    ApplicationContext ctx = SpringApplication.run(Application.class, args);

    LogUtil.info("Beans provided by Spring Boot:");
    String[] beanNames = ctx.getBeanDefinitionNames();
    Arrays.sort(beanNames);
    for (String beanName : beanNames) {
        LogUtil.info(beanName);
    }
    LogUtil.info("Application Boots completes!");
}

@Bean
public CommandService commandService(){
    LogUtil.debug("CommandService.getInstance()"+ CommandService.getInstance()) ;//here indeed I could see spring executes this and returns a object when application boots
    return CommandService.getInstance();//This returns a singleton instance
}

}

My controller that throws null pointer:

@Controller
public class CoreController {

    @Autowired
    CommandService commandService;//here the service is null after using aop

    //...some request methods
}

The Aspect which I added just now:

//if I comment out these two annoations, the bean will be auto injected well
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* wodinow.weixin.jaskey..*.*(..))")
    private void debug_log(){};

    @Around("debug_log()")
    public void debug(ProceedingJoinPoint joinPoint) throws Throwable{
        LogUtil.debug("enter "+joinPoint.getSignature());
        try{
           joinPoint.proceed();
           LogUtil.debug("returns from "+joinPoint.getSignature());
        }
        catch(Throwable t){
            LogUtil.error(t.getMessage()+"occurs in "+joinPoint.getSignature(),t);
            throw t;
        }
    }
}

I am new to Spring, can anybody help me with this?


Solution

  • Your @ComponentScan is trying to resolve and autowire your dependencies into CoreController. When it tries to resolve the dependency it finds the @Bean in your Application class. It then tries to resolve this dependency by calling Application.commandService(). When this method is called, it sees the matching @Pointcut and invokes your advice method. Since your @Advice is not returning anything, the callers will also see that nothing was returned, and it will say that that resolution of that dependency returned null.

    The fix here is just to change your @Around advice to return the value of your invocation.

    @Around("debug_log()")
    public Object debug(ProceedingJoinPoint joinPoint) throws Throwable{
        LogUtil.debug("enter "+joinPoint.getSignature());
        try{
            // return the invocation
            return joinPoint.proceed();
        }
        catch(Throwable t){
            LogUtil.debug(t.getMessage()+"occurs in "+joinPoint.getSignature(),t);
            throw t;
        }
    }