静态方法使用@Autowired注入

本文详细解析了Java中@Autowired注解的使用场景和注意事项,包括构造方法和静态方法中的使用,以及如何解决由此引发的NullPointerException异常。同时介绍了通过ApplicationContext、@PostConstruct注解和构造方法初始化静态变量的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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进行组建注册的时候会进行初始化,初始化后赋值到变量,所以还有一个遗留问题,就是不能在构造器内调用静态变量

<think>好的,用户遇到了在Spring Boot 3中使用@Autowired注解时AdminMapper为null的问题。我需要先分析可能的原因,然后根据提供的引用资料逐一排查。 首先,根据引用[1]和[2],注入为null可能是因为Bean的生成顺序问题,或者是在非Spring管理的类中使用@Autowired。比如用户可能在手动new的对象中尝试注入,这会导致失败,因为Spring无法管理这些实例。这时候需要确保AdminMapper所在的类本身是被Spring容器管理的,比如添加了@Component或@Service等注解。 其次,引用[3]提到在静态变量或线程中使用@Autowired会导致问题,因为Spring无法注入静态成员。如果用户将AdminMapper声明为static,那肯定会是null。需要检查代码中是否有这样的错误用法,并改为非静态变量。 然后,引用[4]指出访问权限的问题,如果注入的方法或字段是private的,某些情况下会导致注入失败。虽然Spring通常能通过反射注入private字段,但最好还是将字段设为public或使用setter方法,确保注入成功。 接下来,可能的解决方案包括:检查类是否被Spring管理,确保AdminMapper有正确的注解如@Mapper或@Repository;检查是否有循环依赖;使用构造函数注入代替字段注入,因为构造函数注入更可靠,特别是在Spring Boot 3中可能更推荐这种方式。 另外,如果用户是在自定义的过滤器或Servlet等非Spring管理的组件中使用@Autowired,可能需要通过ApplicationContext手动获取Bean,如实现ApplicationContextAware接口,或者使用@Configurable注解。 还需要考虑是否在测试环境中正确配置了上下文,比如在单元测试中使用@SpringBootTest注解来启动完整的Spring上下文,避免在普通测试中无法注入的情况。 最后,建议用户检查依赖配置,确保Spring Boot 3的相关依赖正确,特别是如果AdminMapper是MyBatis的Mapper,需要确认是否添加了@MapperScan注解来扫描对应的接口。 总结一下,可能的解决步骤是:检查类是否被Spring管理,检查静态变量,检查访问权限,使用构造函数注入,处理非Spring管理的类,检查依赖配置和注解,以及处理测试环境的问题。</think>### Spring Boot 3中@Autowired导致AdminMapper为空的解决方案 #### 1. **检查类是否被Spring管理** - **问题**:如果包含`AdminMapper`的类未被Spring容器管理(例如未添加`@Component`、`@Service`、`@Controller`等注解),则无法通过`@Autowired`注入依赖。 - **解决方案**:确保类添加了合适的注解。例如: ```java @Service public class AdminService { @Autowired private AdminMapper adminMapper; } ``` #### 2. **避免静态变量注入** - **问题**:若将`AdminMapper`声明为`static`字段,Spring无法注入静态成员[^3]。 - **解决方案**:移除`static`关键字,改为非静态字段: ```java @Autowired private AdminMapper adminMapper; // 非static ``` #### 3. **检查访问权限** - **问题**:若字段或方法为`private`且未提供`public`的`setter`方法,可能导致注入失败(尤其在旧版本Spring中)[^4]。 - **解决方案**:将字段设为`public`或提供`setter`方法: ```java @Autowired public void setAdminMapper(AdminMapper adminMapper) { this.adminMapper = adminMapper; } ``` #### 4. **使用构造函数注入(推荐)** - **问题**:字段注入(`@Autowired`直接标注字段)可能因Bean初始化顺序导致问题。 - **解决方案**:改用构造函数注入,Spring Boot 3推荐此方式: ```java @Service public class AdminService { private final AdminMapper adminMapper; public AdminService(AdminMapper adminMapper) { this.adminMapper = adminMapper; } } ``` #### 5. **处理非Spring管理的类** - **问题**:在手动`new`的类(如工具类、过滤器、线程)中无法直接使用`@Autowired`[^2]。 - **解决方案**: - **方法1**:通过`ApplicationContext`手动获取Bean: ```java @Component public class MyUtils implements ApplicationContextAware { private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) { context = applicationContext; } public static AdminMapper getAdminMapper() { return context.getBean(AdminMapper.class); } } ``` - **方法2**:使用`@Configurable`注解(需开启AspectJ支持): ```java @Configurable public class CustomClass { @Autowired private AdminMapper adminMapper; } ``` #### 6. **检查Mapper接口配置** - **问题**:若`AdminMapper`是MyBatis接口,需确保正确配置`@Mapper`或`@MapperScan`。 - **解决方案**: ```java @Mapper public interface AdminMapper { // SQL方法 } ``` 或在启动类添加扫描: ```java @SpringBootApplication @MapperScan("com.example.mapper") public class Application { ... } ``` #### 7. **排除循环依赖** - **问题**:若`AdminService`与`AdminMapper`存在循环依赖,可能导致Bean初始化失败。 - **解决方案**:重构代码逻辑,或使用`@Lazy`延迟注入: ```java @Autowired @Lazy private AdminMapper adminMapper; ``` #### 8. **测试环境配置** - **问题**:单元测试中未正确加载Spring上下文。 - **解决方案**:使用`@SpringBootTest`注解: ```java @SpringBootTest class AdminServiceTest { @Autowired private AdminMapper adminMapper; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值