不用注入方式使用Spring管理的物件中的方法,神奇

秦蕭冷發表於2020-07-30

在小冷工作中遇到這麼一個小問題,當你的業務層物件交給spring管理之後,在普通的類中呼叫這個類中的方法時候,會有個問題這個類在呼叫時候會一直返回一個null,而且還會丟擲一個空指標異常。

小冷在遇到這個問題時候使用了各種方法發現很多都不能用,其中小冷羅列下生效的方法,並且網上還推薦使用的

1.在普通類種也將自己注入交給spring管理

不用注入方式使用Spring管理的物件中的方法,神奇

不用注入方式使用Spring管理的物件中的方法,神奇

首先看上面的,第一張圖片,那個普通類似交給了spring管理的,並在這個類中注入了使用的業務層類,這個時候呼叫這個類中的方法時候,發現這個業務類返回是一個null,至於原因小冷下面解釋。

還有一種

2.小冷使用例項化這個業務類,一般例項化的類會加入堆記憶體的這樣試一下發現也不行

不用注入方式使用Spring管理的物件中的方法,神奇

不用注入方式使用Spring管理的物件中的方法,神奇

3.使用類載入的方式將載入器在專案啟動時就呼叫這個載入器,然後通過載入後的spring類載入器呼叫載入,這種是可以的

不用注入方式使用Spring管理的物件中的方法,神奇

綜上所述只有第三種方法可以,這個裡附上載入spring容器的中的例項化類的工具類

package com.util;
/*
 * @desc:提供非SPRING管理類呼叫管理類的功能
 * 注意在服務啟動的時候進行import,apllication中引入
 */
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
​
​
@Component
public class SpringUtil implements ApplicationContextAware {
       private static ApplicationContext applicationContext = null;
​
       @Override
​
       public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
​
              if (SpringUtil.applicationContext == null) {
                     SpringUtil.applicationContext = applicationContext;
              }
              System.out.println("---------------------------------------------------------------------");
              System.out.println("========ApplicationContext配置成功,在普通類可以通過呼叫SpringUtils.getAppContext()獲取applicationContext物件,applicationContext=" + SpringUtil.applicationContext + "========");
              System.out.println("---------------------------------------------------------------------");
       }
​
       //獲取applicationContext
       public static ApplicationContext getApplicationContext() {
              return applicationContext;
       }
​
       //通過name獲取 Bean.
       public static Object getBean(String name) {
              return getApplicationContext().getBean(name);
       }
​
       //通過class獲取Bean.
       public static <T> T getBean(Class<T> clazz) {
              return getApplicationContext().getBean(clazz);
       }
​
       //通過name,以及Clazz返回指定的Bean
       public static <T> T getBean(String name, Class<T> clazz) {
              return getApplicationContext().getBean(name, clazz);
       }
}

使用方式工具類中有註釋;就不一一贅述

這裡小冷按自己理解說一下為啥前兩種方式無法使用,如有不同理解和更為準確的解釋歡迎私信留言!!!!關注我公眾號“秦川以北”

先說一下第一種:小冷理解在看原始碼時候是由於在使用@Component註解和@Autowired時注入的例項未初始化,這時候spring容器中接收不到未初始化的例項,這個解決方案,在注入的同時初始化這個例項讓spring掃描到這個例項然後加入容器

@Component
public class ComponentClass {
​
    @Autowired
    private JedisClient jedisClient;
    public static ComponentClass componentClass;
    @PostConstruct
    public void init(){
        componentClass = this;
        componentClass.jedisClient = this.jedisClient;
    }
}

第二種:第二種事由於例項化的業務類在自己類種引用了spring容器種的例項類,這個時候例項化的類在堆記憶體種,而spring容器在自己的堆存種中,他們不在同一個堆中可能這是例項化失效的關鍵。

以上都是小冷個人理解如有不同見解歡迎留言懟,有的原始碼小冷也是看的一知半解。不用注入方式使用Spring管理的物件中的方法,神奇

不用注入方式使用Spring管理的物件中的方法,神奇

相關文章