Java变量的初始化顺序为:静态变量或静态代码块–>实例变量或初始化代码块–>构造方法–>@Autowired(@Autowired:会在类的加载最后随着类的普通方法的需要注入,并且如果类中使用@Autowired注入的类中也使用@Autowired注解注入了用@Component、@Repository、@Service、@Controller修饰过交给Spring容器管理的类,那么也需要使用Spring容器或者applicationcontext上下文进行注入,手动实例化或者使用Java反射使用会失效,获得Null。) 允许多个相同的类@Autowired注入,但得到的是同一个实例,因为Bean是单例。
那么需要注意的点有两个,一.关于构造方法使用@Autowired的类,二.Static方法使用@Autowired的类。
1.关于构造方法使用@Autowired的类
@Autowired
CategoryMapper categoryMapper;
private List<Category> categoryList = categoryMapper.selectByExample(new CategoryExample());
这段代码报java.lang.NullPointerException: null异常。报错信息说:该类初始化时出错,出错原因是实例化bean时构造方法出错,在构造方法里抛出了空指针异常。
解决办法:
使用构造器注入的方法,明确了成员变量的加载顺序。如下
private CategoryMapper categoryMapper;
private List<Category> categoryList;
@Autowired
public CategoryServiceImpl(CategoryMapper categoryMapper) {
this.categoryMapper = categoryMapper;
this.categoryList = categoryMapper.selectByExample(new CategoryExample());
}
2.关于Static方法使用@Autowired的类的几种方法。
(1)使用ApplicationContext
package com.cn.common.util.EasyCaptcha;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Title: SpringContextUtil
*
* Description: 实现对spring context 的管理
*
* @author xiaojihuibengdi Date: 2019年6月5日 下午11:20:29
*/
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
/**
* 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
/**
* 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
/**
* 获取类型为requiredType的对象 如果bean不能被类型转换,相应的异常将会被抛出(BeanNotOfRequiredTypeException)
*/
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
*/
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
* 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
*/
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
/**
* Class 注册对象的类型
*/
public static Class<?> getType(String name) {
return applicationContext.getType(name);
}
}
在使用的过程
package com.cn.common.util.EasyCaptcha;
import java.awt.Font;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.springframework.retry.RetryException;
import org.springframework.stereotype.Component;
import com.wf.captcha.Captcha;
import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha;
/**
* 验证码工具类
*
*
* @author wanghao
*/
@Component
public class CaptchaUtil {
private static RedisCacheManager cacheManager = SpringContextUtil.getBean(RedisCacheManager.class);
// 不要更改顺序,很重要!!!
public static String verificationCode;
// gif 类型验证码
private static final int GIF_TYPE = 1;
// png 类型验证码
private static final int PNG_TYPE = 0;
// 验证码图片默认高度
private static final int DEFAULT_HEIGHT = 48;
// 验证码图片默认宽度
private static final int DEFAULT_WIDTH = 130;
// 验证码默认位数
private static final int DEFAULT_LEN = 5;
public static void out(HttpServletRequest request, HttpServletResponse response) throws IOException {
out(DEFAULT_LEN, request, response);
}
public static void out(int len, HttpServletRequest request, HttpServletResponse response) throws IOException {
out(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, null, request, response);
}
public static void out(int len, Font font, HttpServletRequest request, HttpServletResponse response) throws IOException {
out(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, null, font, request, response);
}
public static void out(int width, int height, int len, Integer vType, HttpServletRequest request, HttpServletResponse response) throws IOException {
out(width, height, len, vType, null, request, response);
}
public static void out(int width, int height, int len, Integer vType, Font font, HttpServletRequest request, HttpServletResponse response) throws IOException {
outCaptcha(width, height, len, font, GIF_TYPE, vType, request, response);
}
public static void outPng(HttpServletRequest request, HttpServletResponse response) throws IOException {
outPng(DEFAULT_LEN, request, response);
}
public static void outPng(int len, HttpServletRequest request, HttpServletResponse response) throws IOException {
outPng(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, null, request, response);
}
public static void outPng(int len, Font font, HttpServletRequest request, HttpServletResponse response) throws IOException {
outPng(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, null, font, request, response);
}
public static void outPng(int width, int height, int len, Integer vType, HttpServletRequest request, HttpServletResponse response) throws IOException {
outPng(width, height, len, vType, null, request, response);
}
public static void outPng(int width, int height, int len, Integer vType, Font font, HttpServletRequest request, HttpServletResponse response) throws IOException {
outCaptcha(width, height, len, font, PNG_TYPE, vType, request, response);
}
/**
* Title: outCaptcha
* <p>
* Description: 获取验证码
* </p>
*
* @author: wanghao
* @param request
* @param response
* @throws Exception void 返回类型
*/
private static void outCaptcha(int width, int height, int len, Font font, int cType, Integer vType, HttpServletRequest request, HttpServletResponse response) throws IOException {
setHeader(response, cType);
Captcha captcha = null;
if (cType == GIF_TYPE) {
captcha = new GifCaptcha(width, height, len);
} else {
captcha = new SpecCaptcha(width, height, len);
}
if (font != null) {
captcha.setFont(font);
}
if (vType != null) {
captcha.setCharType(vType);
}
HttpSession session = request.getSession();
verificationCode = captcha.text().toLowerCase();
captcha.out(response.getOutputStream());
}
//设置验证码相关信息 提供gif 或 png 两种格式
public static void setHeader(HttpServletResponse response, int cType) {
if (cType == GIF_TYPE) {
response.setContentType("image/gif");
} else {
response.setContentType("image/png");
}
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0L);
}
}
(2)使用注解@PostConstruct
@Component
public class Boo {
private static Foo foo;
@Autowired
private Foo tFoo;
@PostConstruct
public void init() {
Boo.foo = tFoo;
}
public static void randomMethod() {
foo.doStuff();
}
}
(3)利用构造方法
@Component
public class AA {
private static Object variable;
@Autowired
public AA(Object variable) {
AA.variable = variable;
}
}
在spring进行组建注册的时候会进行初始化,初始化后赋值到变量,所以还有一个遗留问题,就是不能在构造器内调用静态变量