Spring 中 @Autowired 注解和静态方法关联应用

本贴最后更新于 2170 天前,其中的信息可能已经水流花落

Spring 中 @Autowired 注解和静态方法关联应用

一、业务场景

spring 框架应用中有些静态方法需要依赖被容器管理的类,就像这样:

@Component
public class Test {
    
    @Autowired
    private static UserService userService;
    
    public static void test() {
        userService.test();
    }
}

这样一定会报 java.lang.NullPointerException: null 异常。

二、原理剖析

静态变量、类变量不是对象的属性,而是一个类的属性,所以静态方法是属于类(class)的,普通方法才是属于实体对象(也就是 New 出来的对象)的,spring 注入是在容器中实例化对象,所以不能使用静态方法。

而使用静态变量、类变量扩大了静态方法的使用范围。静态方法在 spring 是不推荐使用的,依赖注入的主要目的,是让容器去产生一个对象的实例,然后在整个生命周期中使用他们,同时也让 testing 工作更加容易。

一旦你使用静态方法,就不再需要去产生这个类的实例,这会让 testing 变得更加困难,同时你也不能为一个给定的类,依靠注入方式去产生多个具有不同的依赖环境的实例,这种 static field 是隐含共享的,并且是一种 global 全局状态,spring 同样不推荐这样去做。

在 Springframework 里,我们是不能 @Autowired 一个静态变量,使之成为一个 Spring bean 的。为什么?其实很简单,因为当类加载器加载静态变量时,Spring 上下文尚未加载。所以类加载器不会在 bean 中正确注入静态类,并且会失败。

三、解决方法

1、将 @Autowire 加到构造方法上

@Component
public class Test {
    
    private static UserService userService;
    
    @Autowired
    public Test(UserService userService) {
        Test.userService = userService;
    }
    
    public static void test() {
        userService.test();
    }
}

2、用 @PostConstruct 注解

@Component
public class Test {
    
    private static UserService userService;
    
    @Autowired
    private UserService userService2;
    
    @PostConstruct
    public void beforeInit() {
        userService = userService2;
    }
    
    public static void test() {
        userService.test();
    }
}

四、真实案例

代码如下:

package com.lxxfjr.microbank.integration.gateway;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.lxxfjr.microbank.common.util.StringUtil;
import com.lxxfjr.microbank.common.util.security.GateWayRSACoder;
import com.lxxfjr.microbank.dal.daointerface.ApplicationIPWhiteListDAO;
import com.lxxfjr.microbank.dal.daointerface.ExternalKeyInfoDAO;
import com.lxxfjr.microbank.dal.daointerface.SysParamDAO;
import com.lxxfjr.microbank.dal.dataobject.ApplicationIPWhiteListDO;
import com.lxxfjr.microbank.dal.dataobject.ExternalKeyInfoDO;
import com.lxxfjr.microbank.dal.dataobject.SysParamDO;
import com.yjf.common.log.Logger;
import com.yjf.common.log.LoggerFactory;

/**
 * 网关相关验证类
 * 
 * @author lujl
 * @date 2018-12-12
 */
@Component
public class GateWayValidationUtil {

	private static GateWayValidationUtil gateWay;
	
	@Autowired
	protected SysParamDAO sysParamDAO;
	
	@Autowired
	protected ApplicationIPWhiteListDAO applicationIPWhiteListDAO;
	
	@Autowired
	protected ExternalKeyInfoDAO externalKeyInfoDAO;
	
	
	protected final static Logger logger = LoggerFactory.getLogger(GateWayValidationUtil.class);
	
	@PostConstruct  
	public void init() {       
		gateWay = this; 
		gateWay.sysParamDAO = this.sysParamDAO;
		gateWay.applicationIPWhiteListDAO = this.applicationIPWhiteListDAO;
		gateWay.externalKeyInfoDAO = this.externalKeyInfoDAO;
	} 
	
	/**
	 * IP地址白名单验证
	 * 
	 * @param partnerNo
	 *            合作方编号
	 * @param ipAddress
	 *            IP地址
	 * @return {@code true} 允许;{@code false} 不允许;
	 */
	public static boolean isIPPermitConnection(String partnerNo,String ipAddress) {
		
		/** 业务逻辑开始 **/
		// 白名单验证:判断是否需要检验,从系统配置表sys_param查询
		SysParamDO sysParamDOTemp = gateWay.sysParamDAO.findById("CHECK_WHITELIST_DATA");

		logger.info("平台服务器地址:" + ipAddress);

		ApplicationIPWhiteListDO applicationIPWhiteListInfo = new ApplicationIPWhiteListDO();

		// 开启白名单验证的场合-平台参数【YES】
		if (StringUtil.isNotEmpty(checkWhiteListDate) && checkWhiteListDate.equals("YES")) {

			// 只找同平台下的
			applicationIPWhiteListInfo.setSource(partnerNo);
			
			//查询external_server_ip_white_info外部白名单表,首先得有至少一条配置
			long count = gateWay.applicationIPWhiteListDAO
					.findApplicationIPWhiteListCountByCondition(applicationIPWhiteListInfo, null, null);
			if(count==0) {
				return false;
			}
			
			List<ApplicationIPWhiteListDO> applicationIPWhiteListDOs = gateWay.applicationIPWhiteListDAO
					.findApplicationIPWhiteListInfoByCondition(applicationIPWhiteListInfo, 0, count, null, null);
		}else {
			//未开启验证的场合,直接允许通过
			return true;
		}
		 
	}
	
	/**
	 * 业务数据一致性验证
	 * @param request
	 * 			请求体
	 * @return  {@code true} 一致;{@code false} 不一致;
	 */
	public static boolean dataConsistencyCheck(HttpServletRequest request) {

		Map<String, String> map = new HashMap<String, String>();

		//业务数据不存在直接返回错误
		if(bizdata==null || "".equals(bizdata)){
			return false ;
		}
		
		// 检索外部接口验证键表,获取给平台分配的公钥密钥
		ExternalKeyInfoDO externalKeyInfoDO = null;
		try {
			externalKeyInfoDO = gateWay.externalKeyInfoDAO.findByPartnerNo(partnerNo);	
		} catch (Exception e) {
			return false;
		}

		
		// 一致的验签不通过
		if (!isSignOk) {
			logger.error("一致的验签不通过: partnerNo=" + partnerNo);
			return false;
		}else {
			return true;
		}	
	}

}
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3453 回帖 • 203 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    944 引用 • 1459 回帖 • 17 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...