Java 在Controller层 private修饰的方法导致Service注入为空

4,335 阅读2分钟

背景:某日在公司中撸代码的时候,在一个常用的controller中添加一个方法,测试时突然报错说注入的service为null,捣鼓一阵发现后是方法修饰符写成private,修改成public后搞定。为什么会产生这个问题呢?就自己测试一下是哪里发生了问题

首先简单模拟一下环境

public interface TestService {
    String getTestString();
}


@Service("testService")
public class TestServiceImpl implements TestService {
    @Override
    public String getTestString() {
        return "hinotoyk";
    }
}
    

@RestController
public class MainController {
    @Autowired
    private TestService service;

    @RequestMapping("/testA")
    public String testA(){
        return service.getTestString();
    }
    @RequestMapping("/testB")
    private String testB(){
        return service.getTestString();
    }

}

/testA是pulibc,/testB是pirvate,测试结果均能返回"hinotoyk"字符串

测试和公司环境还有一个不太同的就是公司项目中有Aop切面处理访问日志的,还要添加一个Aop

@Aspect
@Component
public class WebLogAspect {
    private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    @Pointcut("execution(public * com.spring.controller..*.*(..))")
    public void controllerLog(){}

    @Before("controllerLog()")
    public void logBeforeController(JoinPoint joinPoint) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        logger.info("*************URL : " + request.getRequestURL().toString());
        logger.info("*************HTTP_METHOD : " + request.getMethod());
        logger.info("*************IP : " + request.getRemoteAddr());
    }    
}

添加了一个Aop后测试
/testA返回"hinotoyk"字符串
/testB访问报错,service注入失败,为null

为什么使用Aop会导致private修饰的方法注入失败,查询了许多资料后发现一位老哥的SpringAOP导致@Autowired依赖注入失败中说到org.springframework.aop.support.AopUtils中的代码使用的是Method[] methods = clazz.getMethods(),即是只能拿到public方法。但是我使用的版本2.1.4.RELEASE中已经使用Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);这就有点迷惑了

会不会是切点注解中的修饰符匹配不到呢?将切点中的修饰符从public修改成private

 @Pointcut("execution(private* com.spring.controller..*.*(..))")
    public void controllerLog(){}

测试结果
/testA返回"hinotoyk"字符串
/testB访问报错,service注入失败,为null

还是不行(就挺秃然的)

目前结论

  1. 方法中没有用@Autowired或者@Resource注入的对象。有无Aop,任意修饰符都可以正常访问并且返回结果
  2. 方法中使用了@Autowired或者@Resource注入的对象
    没有Aop切面的情况下,public,protected,private都能正常的映射
    在有Aop切面的情况下,public,protected可以正常映射,但是使用private会报空指针异常,注入对象为null