静态方法注入bean失败原因

今天在写redission 的一个工具类的时候,随手写出下面的代码

package com.wt.redission.wtredission.utils;


import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class RedissionUtilserror {

    @Autowired
   private static RedissonClient redissonClient;

    

    public static RLock getRLock(String objectName) {
        RLock rLock =redissonClient.getLock(objectName);
        return rLock;
    }


    //根据名字获取map
    public static  <K, V> RMap<K, V> getRMap(String objectName) {
        RMap<K, V> map = redissonClient.getMap(objectName);
        return map;
    }

    //根据名字和值设置map
    public static void setMap(String objectName,Object key,Object value){
        RMap<Object, Object> map =redissonClient.getMap(objectName);
        map.put(key,value);
    }


    //根据名字获取set
    public static <V> RSet<V> getSet(String objectName) {
        RSet<V> set = redissonClient.getSet(objectName);
        return set;
    }

    //根据名字和值设置set
    public static void setSet(String objectName,Object value){
        RSet<Object> set = redissonClient.getSet(objectName);
        set.add(value);
    }

    //根据名字获取list
    public static  <V> RList<V> getRList(String objectName) {
        RList<V> rList = redissonClient.getList(objectName);
        return rList;
    }


    //根据名字和值设置list
    public static void setList(String objectName, int  index,Object element ){
        RList<Object> objectRList = redissonClient.getList(objectName);
        objectRList.set(index,element);
    }

    //根据名字获取bucket
    public static <T> RBucket<T> getRBucket(String objectName) {
        RBucket<T> bucket = redissonClient.getBucket(objectName);
        return bucket;
    }

    //根据名字和值 设置对应的bucket
    public static  <T> T setBucket(String objectName,String value){
        RBucket<Object> bucket = redissonClient.getBucket(objectName);
        bucket.set(value);
        T t= (T) bucket.get(); //值类型由返回值确定
        return  t;
    }

}

 乍一看好像没问题 我写一个静态方法 然后在方法中使用静态变量redissonClient ,哇....,一切看得如此正常

当我开始测试时,NPE.............,我去这是怎么回事,自己在想这不科学啊,怎么会空指针,于是我开始找原因

最后发现是基础不牢啊............,对jvm的类加载机制几乎就没考虑,简要说要错误的原因

jvm在进行类加载的时候,首先会加载类变量,类方法,也就是我这里被static修饰的方法,然后当我调用静态方法进行使用的时候,会使用到redissionClient,注意这个redissionClient是通过autowired进来的,关键问题就在这里,autowired的底层是通过构造器和set方法注入bean的

redissionClient被static修饰 并且还是一个接口 在被调用的时候肯定没有实例化

下面提供三种方式正确使用

 

方式一  

package com.wt.redission.wtredission.utils;


import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class RedissionUtils {

    private static RedissonClient redissonClient;

    @Autowired
    public  RedissionUtils(RedissonClient redissonClient){
        RedissionUtils.redissonClient=redissonClient;
    }



    public static RLock getRLock(String objectName) {
        RLock rLock = redissonClient.getLock(objectName);
        return rLock;
    }


    //根据名字获取map
    public static  <K, V> RMap<K, V> getRMap(String objectName) {
        RMap<K, V> map = redissonClient.getMap(objectName);
        return map;
    }

    //根据名字和值设置map
    public static void setMap(String objectName,Object key,Object value){
        RMap<Object, Object> map =redissonClient.getMap(objectName);
        map.put(key,value);
    }


    //根据名字获取set
    public static <V> RSet<V> getSet(String objectName) {
        RSet<V> set = redissonClient.getSet(objectName);
        return set;
    }

    //根据名字和值设置set
    public static void setSet(String objectName,Object value){
        RSet<Object> set = redissonClient.getSet(objectName);
        set.add(value);
    }

    //根据名字获取list
    public static  <V> RList<V> getRList(String objectName) {
        RList<V> rList = redissonClient.getList(objectName);
        return rList;
    }


    //根据名字和值设置list
    public static void setList(String objectName, int  index,Object element ){
        RList<Object> objectRList = redissonClient.getList(objectName);
        objectRList.set(index,element);
    }

    //根据名字获取bucket
    public static <T> RBucket<T> getRBucket(String objectName) {
        RBucket<T> bucket = redissonClient.getBucket(objectName);
        return bucket;
    }

    //根据名字和值 设置对应的bucket
    public static  <T> T setBucket(String objectName,String value){
        RBucket<Object> bucket = redissonClient.getBucket(objectName);
        bucket.set(value);
        T t= (T) bucket.get(); //值类型由返回值确定
        return  t;
    }

}

方式二

package com.wt.redission.wtredission.utils;


import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class RedissionUtils2 {

    @Autowired
    RedissonClient redissonClient;

    public  static RedissionUtils2 redissionUtils;

    @PostConstruct
    public  void  init(){
        redissionUtils=this;
        redissionUtils.redissonClient=this.redissonClient;
    }



    public static RLock getRLock(String objectName) {
        RLock rLock = redissionUtils.redissonClient.getLock(objectName);
        return rLock;
    }


    //根据名字获取map
    public static  <K, V> RMap<K, V> getRMap(String objectName) {
        RMap<K, V> map = redissionUtils.redissonClient.getMap(objectName);
        return map;
    }

    //根据名字和值设置map
    public static void setMap(String objectName,Object key,Object value){
        RMap<Object, Object> map =redissionUtils.redissonClient.getMap(objectName);
        map.put(key,value);
    }


    //根据名字获取set
    public static <V> RSet<V> getSet(String objectName) {
        RSet<V> set = redissionUtils.redissonClient.getSet(objectName);
        return set;
    }

    //根据名字和值设置set
    public static void setSet(String objectName,Object value){
        RSet<Object> set = redissionUtils.redissonClient.getSet(objectName);
        set.add(value);
    }

    //根据名字获取list
    public static  <V> RList<V> getRList(String objectName) {
        RList<V> rList = redissionUtils.redissonClient.getList(objectName);
        return rList;
    }


    //根据名字和值设置list
    public static void setList(String objectName, int  index,Object element ){
        RList<Object> objectRList = redissionUtils.redissonClient.getList(objectName);
        objectRList.set(index,element);
    }

    //根据名字获取bucket
    public static <T> RBucket<T> getRBucket(String objectName) {
        RBucket<T> bucket = redissionUtils.redissonClient.getBucket(objectName);
        return bucket;
    }

    //根据名字和值 设置对应的bucket
    public static  <T> T setBucket(String objectName,String value){
        RBucket<Object> bucket = redissionUtils.redissonClient.getBucket(objectName);
        bucket.set(value);
        T t= (T) bucket.get(); //值类型由返回值确定
        return  t;
    }

}

方式三  通过spring上下文获取

package com.wt.redission.wtredission.utils;


import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * Spring Context工具类.
 *
 * @author:Hohn
 */
@Component
@Scope("singleton")
public class SpringUtil implements ApplicationContextAware {

    /**
     * Spring应用上下文环境.
     */
    private static ApplicationContext applicationContext;

    /**
     * 实现ApplicationContextAware接口的回调方法,设置上下文环境
     *
     * <br>🌹param: applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SpringUtil.applicationContext = applicationContext;
    }

    /**
     * 获取ApplicationContext.
     *
     * <br>🌹return: ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 获取对象.
     *
     * <br>🌹param: name
     * <br>🌹return: Object 一个以所给名字注册的bean的实例
     * @throws BeansException
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) applicationContext.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象.
     *
     * <br>🌹param: clz
     * <br>🌹return:
     * @throws BeansException
     */
    public static <T> T getBean(Class<T> clz) throws BeansException {
        return (T)applicationContext.getBean(clz);
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * <br>🌹param: name
     * <br>🌹return: boolean
     */
    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
     * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     * <br>🌹param: name
     * <br>🌹return: boolean
     * @throws NoSuchBeanDefinitionException
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.isSingleton(name);
    }

    /**
     * <br>🌹param: name
     * <br>🌹return: Class 注册对象的类型
     * @throws NoSuchBeanDefinitionException
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * <br>🌹param: name
     * <br>🌹return:
     * @throws NoSuchBeanDefinitionException
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return applicationContext.getAliases(name);
    }


	/**
	 * 请求头获取请求token
	 * @param servletRequest
	 * @return
	 */
	public static String getJwtToken(HttpServletRequest servletRequest, String tokenId) {
		String token = servletRequest.getHeader(tokenId);
		if (StringUtils.isBlank(token)) {
			token = servletRequest.getParameter(tokenId);
		}
		return token;
	}
}

 

 

 

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值