栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring在使用的类方法里仍能使用注入的依赖的相关措施

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring在使用的类方法里仍能使用注入的依赖的相关措施

今天依要求做一个数据字典的模块,其中要做的一个业务是更新数据字典后删除对应的缓存,这里要求使用类方法。一开始我是这么写的。(改动的是refreshCacheByEntryId() )

错误写法1:类方法里含有没有static修饰的对象
@Component
@Log4j2
public class DictUtils {

  private static DictUtils dictUtils;
  @Autowired
  private DictEntryService dictEntryService;

 @Value("${spring.profiles.active}")
 private  String env;

  public static void initMap(){
    bitMap = MapUtil.newHashMap();
    log.error("缓存Map清除完毕");
  }  

 // 刷单个redis的dict
  public static void refreshCacheByEntryId(@NotNull String entryId){
    boolean b = false;
    // 这里也会爆红
    if( this.env.equals("dev") ){
    // 此处会在这里报红
      DictEntry entry = dictEntryService.getByEntityId(entryId);
      ...
  }
}

这种方式在DictEntry entry = dictEntryService.getByEntityId(entryId);这一行就开始报红了,也就是说不能后在类方法里访问本类的属性

错误写法2:没有用static修饰方法

然后试了下吧static给去掉

@Component
@Log4j2
public class DictUtils {

  private static DictUtils dictUtils;
  @Autowired
  private DictEntryService dictEntryService;

// 加上了static
 @Value("${spring.profiles.active}")
 private static String env;

public static void initMap(){
    bitMap = MapUtil.newHashMap();
    log.error("缓存Map清除完毕");
  }  

 // 刷单个redis的dict
  public void refreshCacheByEntryId(@NotNull String entryId){
    boolean b = false;
    
    if( DictUtils.env.equals("dev") ){
    
      DictEntry entry = dictEntryService.getByEntityId(entryId);
      ...
  }
}

这样是不报红了,但是如果在另外一方直接引入的话,比如下方

@RestController("dictEntryController")
@RequestMapping("/api/v1/dict/dictEntry")
public class DictEntryController extends BaseController {
	@Autowired
    private DictEntryService dictEntryService;

	@PutMapping(value = "{id}")
    @ApiOperation(value = "更新对象记s录", notes = "更新对象记录", produces = "application/json")
        public R update(@RequestBody DictEntry entity) {
        R entryR = dictEntryService.update(entity);
        // 清空缓存
        if(entryR.isSuccess()){
        	// 此处在方法执行的时候会报红
            DictUtils.refreshCacheByEntryId(entity.getId());
            System.out.println("111");
        }
        return entryR;
    }

}

会发现执行到 DictUtils.refreshCacheByEntryId(entity.getId());爆红了,因为不能不能直接使用对象方法,只能用new来使用对象方法,那就和一开始我们要的使用类方法来实现不符了

错误写法3:直接同时用static修饰方法,用static修饰依赖

那既然这样,把方法和依赖同时用static来修饰不就可以了么?此处做法会发现一个很大的问题。先黏代码

@Component
@Log4j2
public class DictUtils {

  private static DictUtils dictUtils;

	// 用static修饰
  @Autowired
  private static DictEntryService dictEntryService;

	// 用static修饰
	@Value("${spring.profiles.active}")
     private static String env2;

public static void initMap(){
    ...
  }  

	// 用static修饰方法
  public static void refreshCacheByEntryId(@NotNull String entryId){
    boolean b = false;
    // 用DictUtils.env获取
    if( DictUtils.env.equals("dev") ){
    	// 此处不会爆红,但是会引发注入问题,下文说
      DictEntry entry = dictEntryService.getByEntityId(entryId);
      ...
  }
}

然后另一方的调用

@RestController("dictEntryController")
@RequestMapping("/api/v1/dict/dictEntry")
public class DictEntryController extends BaseController {
	@Autowired
    private DictEntryService dictEntryService;

	@PutMapping(value = "{id}")
    @ApiOperation(value = "更新对象记s录", notes = "更新对象记录", produces = "application/json")
        public R update(@RequestBody DictEntry entity) {
        R entryR = dictEntryService.update(entity);
      
        if(entryR.isSuccess()){
        	// 此处不报红了
            DictUtils.refreshCacheByEntryId(entity.getId());
        }
        return entryR;
    }

}

然后接下来发现运行的时候,报错了,报了个null指针,在哪里报错了?
而且发现env也为null ,@Value注解获取配置文件的值env失败了

	// 就是这一行,env为null
		if( DictUtils.env.equals("dev") ){
        	// 这一行也是,此时dictEntryService为null
            DictUtils.refreshCacheByEntryId(entity.getId());
        }
    	
      DictEntry entry = dictEntryService.getByEntityId(entryId);
      ...

奇怪,那dictEntryService不是已经写了@Autowired了么?为什么为null?是注入失败了么?
答案是是的
那该如何解决这个问题 ?

解决问题

答案是如果想要既实用类方法,又要类方法里面的依赖成功注入,那么要这么做

@Component
@Log4j2
public class DictUtils {

	// 此处要加static
  private static DictUtils dictUtils;

	// 此处不用加static
  @Autowired
  private DictEntryService dictEntryService;

	// 此处不用加static
 @Value("${spring.profiles.active}")
 private String env;

  private static Map> bitMap;
  

	// 进行初始化操作赋值
  @PostConstruct
  public void init() {
    dictUtils = this;
    dictUtils.dictEntryService = this.dictEntryService;
    dictUtils.env  = this.env;
    bitMap = MapUtil.newHashMap();
  }

	public static void initMap(){
	    ...
	 }  

  public static void refreshCacheByEntryId(@NotNull String entryId){
    boolean b = false;
    // 此处改成dictUtils
    if( dictUtils.env.equals("dev") ){
    	// 此处改成dictUtils
      DictEntry entry = dictUtils.dictEntryService.getByEntityId(entryId);
      ...
  }
}

此时是可行的,为什么呢?
因为在@PostConstruct注解中,他的执行顺序是在@Autowired之后的,而@Autowired是在装载类之后的
即顺序:装载类——Autowired——PostConstruct
此时dictUtils = this;此时的this才是已经被装配的(类上有 @Component 注解),然后之后使用这种方式就能够完美获得注入的依赖,而且@Value注解也生效了
实现了在spring里使用类方法来实现业务,并且同时能在类方法里使用已经注入的依赖

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1024712.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号