赞
踩
今天一个小伙伴和我说@Autowired 注入的Bean为null值,经过一番沟通后,我发现原来他需要在静态方法中调用容器Bean,大致将代码贴出来给大家看看:
//模拟错误的使用方式
@Autowired
private static RedisUtil redisUtilBean;
public static String getMsgByRedis(){
redisUtilBean.get("xxx") //这里redisUtilBean一定会是NULL值
}
为什么会出现这种情况?原因是Spring容器的依赖注入是依赖set方法,而set方法是实例对象的方法,注入依赖时是无法注入静态成员变量的,在调用的时候依赖的Bean才会为null;
使用@PostConstruct注解,
@Autowired
private RedisUtil redisUtilBean;
//由于静态方法无法使用注入的Bean 定义静态变量
private static RedisUtil redisUtil;
//当容器实例化当前受管Bean时@PostConstruct注解的方法会被自动触发,借此来实现静态变量初始化
@PostConstruct
public void init(){
this.redisUtil = redisUtilBean;
}
public static String getMsgByRedis(){
redisUtil.get("xxx") //这里可以正常使用
}
利用springboot的启动类中,SpringApplication.run() 方法返回的是一个ConfigurableApplicationContext对象通过定义static变量ConfigurableApplicationContext,利用容器的getBean方法获得依赖对象;
@SpringBootApplication
@EnableTransactionManagement
public class Application {
//定义静态的ApplicationContext
public static ConfigurableApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(Application.class, args);
}
}
//调用 注意Application是我们SpringBoot的启动类
public static String getMsgByRedis(){
Application.applicationContext..getBean(RedisUtil .class).get("xxx")
}
在我们以前SpringMVC中常用的工具类,通过实现ApplicationContextAware接口,网上也很多这里就把工具类贴出来即可;
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.toher.common.utils.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext. * * @author 李怀明 * @version 2017-01-02 */ @Component public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext applicationContext; //实现ApplicationContextAware接口的context注入函数, 将其存入静态变量. public void setApplicationContext(ApplicationContext applicationContext) { SpringContextHolder.applicationContext = applicationContext; } //取得存储在静态变量中的ApplicationContext. public static ApplicationContext getApplicationContext() { checkApplicationContext(); return applicationContext; } //从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. @SuppressWarnings("unchecked") public static <T> T getBean(String name) { checkApplicationContext(); return (T) applicationContext.getBean(name); } //从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型. //如果有多个Bean符合Class, 取出第一个. @SuppressWarnings("unchecked") public static <T> T getBean(Class<T> clazz) { checkApplicationContext(); @SuppressWarnings("rawtypes") Map beanMaps = applicationContext.getBeansOfType(clazz); if (beanMaps != null && !beanMaps.isEmpty()) { return (T) beanMaps.values().iterator().next(); } else { return null; } } private static void checkApplicationContext() { if (applicationContext == null) { throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder"); } } public static HttpServletRequest getRequest() { try { return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); } catch (Exception e) { return null; } } }
调用方法:
RedisUtil redisUtil= (RedisUtil) SpringContextHolder.getBean(RedisUtil.class);
以上就是博主整理的几个解决方案,希望能帮助到大家~ 谢谢~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。