一、SpringBoot实现拦截器通过@Autowired注入报mull
拦截器中,通过@Autowired注入依赖报空,是因为拦截器在SpringContext之前注入,造成的null指针
百度解决方式:
1:通过工具类注入
package cn.wanda.common.utils;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @author : WangYuanYi
* @description :
* @create :2021-11-22 16:35:00
*/
public class SpringContextUtil {
private static ApplicationContext applicationContext;
/**
* 获取上下文
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 设置上下文
* @param applicationContext
*/
public static void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtil.applicationContext = applicationContext;
}
/**
* 通过名字获取上下文中的bean
* @param name
* @return
*/
public static Object getBean(String name){
return applicationContext.getBean(name);
}
/**
* 通过类型获取上下文中的bean
* @param requiredType
* @return
*/
public static Object getBean(Class<?> requiredType){
return applicationContext.getBean(requiredType);
}
/**
* 动态注入bean
* @param requiredType 注入类
* @param beanName bean名称
* @return 注入实例
*/
public static Object registerBean(Class<?> requiredType,String beanName){
//将applicationContext转换为ConfigurableApplicationContext
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
//获取BeanFactory
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getAutowireCapableBeanFactory();
//创建bean信息.
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(requiredType);
//动态注册bean.
defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
//获取动态注册的bean.
return configurableApplicationContext.getBean(requiredType);
}
}
import cn.wanda.common.annotation.UserAuth; import cn.wanda.common.base.PerAuthorityEntity; import cn.wanda.common.utils.RedisUtils; import cn.wanda.modules.sso.service.impl.AuthService; import cn.wanda.modules.sso.utils.AuthConstant; import cn.wanda.modules.sys.dao.SysMenuDao; import cn.wanda.modules.sys.entity.SysMenuEntity; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dozer.DozerBeanMapper; import org.springframework.context.annotation.Configuration; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.util.*; /** * 拦截器 通过@UserAuth 实现拦截 * * @author : WangYuanYi * @description : * @create :2021-11-22 09:03:00 */ @Configuration @Slf4j @AllArgsConstructor public class AdminInterceptor implements HandlerInterceptor { private AuthService authService = (AuthService )SpringContextUtil.registerBean(AuthService .calss,"authService "); private SysMenuDao sysMenuDao = (SysMenuDao )SpringContextUtil.registerBean(SysMenuDao .calss,"sysMenuDao ");; public AdminInterceptor() { } }
2:通过@Bean注解注入
package com.csf.config;
import com.csf.interceptor.MyInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
// MyInterceptor 为实现抽象类的类名(public class AdminInterceptor implements HandlerInterceptor )
@Bean
public HandlerInterceptor getMyInterceptor(){
return new AdminInterceptor ();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getMyInterceptor()).addPathPatterns("/add/*");
}
}
这两种方法尝试之后都无效,最终采用方法:
package cn.wanda.common.Interceptor;
import cn.wanda.common.annotation.UserAuth;
import cn.wanda.common.base.PerAuthorityEntity;
import cn.wanda.common.utils.RedisUtils;
import cn.wanda.modules.sso.service.impl.AuthService;
import cn.wanda.modules.sso.utils.AuthConstant;
import cn.wanda.modules.sys.dao.SysMenuDao;
import cn.wanda.modules.sys.entity.SysMenuEntity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dozer.DozerBeanMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.*;
/**
* 拦截器 通过@UserAuth 实现拦截
*
* @author : WangYuanYi
* @description :
* @create :2021-11-22 09:03:00
*/
@Configuration
@Slf4j
@AllArgsConstructor
public class AdminInterceptor implements HandlerInterceptor {
private AuthService authService;
private SysMenuDao sysMenuDao;
private RedisUtils redisUtils;
public AdminInterceptor() {
}
/**
* 目标方法执行之前
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (redisUtils == null) {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
redisUtils = wac.getBean(RedisUtils.class);
}
if (sysMenuDao == null) {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
sysMenuDao = wac.getBean(SysMenuDao.class);
}
if (authService == null) {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
authService = wac.getBean(AuthService.class);
}
System.out.println(redisUtils ,sysMenuDao,authService );
return true;
}
/**
* 目标方法执行完成之后
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 页面渲染以后
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
public static <T> List<T> mapList(Collection sourceList, Class<T> destinationClass) {
DozerBeanMapper dozer = new DozerBeanMapper();
List<T> destinationList = new ArrayList<>();
for (Object sourceObject : sourceList) {
T destinationObject = dozer.map(sourceObject, destinationClass);
destinationList.add(destinationObject);
}
return destinationList;
}
}
二、在staic方法中引入依赖报null
解决方法:
@Aspect
@Component
@AllArgsConstructor
public class UserAuthAspect {
private AuthService authService;
private SysMenuDao sysMenuDao;
private RedisUtils redisUtils;
private static AuthService staticAuthService;
private static SysMenuDao staticSysMenuDao;
private static RedisUtils staticRedisUtils;
@PostConstruct
public void init() {
staticAuthService = authService;
staticSysMenuDao = sysMenuDao;
staticRedisUtils = redisUtils;
}
}
@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。
PostConstruct在构造函数之后执行,init()方法之前执行。
通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
应用:在静态方法中调用依赖注入的Bean中的方法。