解决controller层注入的service为null问题

问题描述

随着项目进展,需要对用户的操作进行日志记录,原有功能接口在这之前都可以正常使用,增加AOP日志后出现service层注入为null:

问题排查

根据详细的错误日志发现,代码中通过@Autowired注解注入的Service类对象为NULL。

原因

后来经过筛查以及和其他Controller层的类进行对比差异,发现接口方法的修饰符是private,而且在这个接口上没有加AOP日志,于是我将其改为public,最后进行测试,不会报错了。

错误代码

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/getUserName")
    private String getUserName() {
        return userService.getUserName();
    }
}

正确代码

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/getUserName")
    public String getUserName() {
        return userService.getUserName();
    }
}

问题复现

新建一个项目

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/getUserName")
    private String getUserName() {
        return userService.getUserName();
    }
}

问题分析

我们这里使用的是CGLIB代理,该代理的原理是:

动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。

既然CGLIB是通过生成子类的方式来创建代理,那么它生成的子类肯定就要继承父类。

关于Java中的继承,有一条很重要的特性就是:

子类拥有父类非 private 的属性、方法。那么也就是说如果父类中有private方法,生成的代理类中是看不到的。

换言之,由CGLIB创建的代理类,不会包含父类中的私有方法。另外由于CGLIB代理类的生成过程,决定了其成员(无论是private还是protected)均是null。

其他原因

1、该类没有托管给Spring 管理

一般在类的上面添加@Component就可以了

2、看你的xxxxxApplication是否在根目录,因为Springboot默认扫描的就是启动类下的目录,当然也可以通过过@ComponenScan注解去指定扫描范围

3、通过new 的方式创建出来的实例是没有交给Spring 进行管理的,没有被Spring 管理的实例,sSpring ring是无法自动注入bean的,所以为null

例如:

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
 
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new SessionInterceptor()).excludePathPatterns("/static/**").addPathPatterns("/**");
  }
}
public class SessionInterceptor  implements HandlerInterceptor {
    @Autowired
    private IUserService  userService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        HttpSession session = httpServletRequest.getSession();
        String username = (String)session.getAttribute("userName");
        //运行时候userService是null
        SysUser userInfo =userService.getUserInfoByUserName(username).get(0);
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值