Rumah  >  Artikel  >  Java  >  Cara menggunakan antara muka lanjutan SpringBoot ApplicationContextAware

Cara menggunakan antara muka lanjutan SpringBoot ApplicationContextAware

王林
王林ke hadapan
2023-05-15 17:04:06958semak imbas

Antara muka ApplicationContextAware:

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

Pertama sekali, antara muka Aware mengetahui bahawa ini adalah sambungan springboot untuk digunakan oleh pengguna Kaedah setApplicationContext disediakan di sini . Kami boleh menerima objek konteks ini Kami Jika anda ingin mengetahui peranan khusus untuk mendapatkan konteks bekas spring ApplicationContext, ini adalah tujuan antara muka lanjutan Dapatkan konteks dan lakukan sesuatu berdasarkan ciri konteks.

Mari kita lihat kaedah objek ApplicationContext:

Cara menggunakan antara muka lanjutan SpringBoot ApplicationContextAware

Mari kita lihat kaedah kelas pelaksanaan AbstractApplicationContext:

rreee

Di sini kita boleh temui getBean Kaedah () sangat biasa, kerana apabila saya mula-mula belajar spring, saya tidak menggunakan perancah spring untuk mencipta projek Cara kami mendapatkan bean biasanya dengan mengimbas fail xml bean dan menghuraikannya untuk membentuk objek ApplicationCOntext, dan kemudian panggil kaedah getBeannya untuk mendapatkan kacang contoh.

Daripada ini kita dapati kaedah aplikasi utama kita adalah menggunakan kaedah getBean ini Kemudian kita boleh menyuntik kacang secara dinamik melalui banyak kaedah, jadi tidak sukar untuk berfikir di sini bahawa kacang yang disuntik tidak boleh digunakan dalam kaedah statik. soalan .

Seterusnya, mari kita hasilkan semula masalah ini Mari kita lihat kod berikut:

    public Object getBean(String name) throws BeansException {this.assertBeanFactoryActive();return this.getBeanFactory().getBean(name);}
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {this.assertBeanFactoryActive();return this.getBeanFactory().getBean(name, requiredType);}
    public Object getBean(String name, Object... args) throws BeansException {this.assertBeanFactoryActive();return this.getBeanFactory().getBean(name, args);}
    public <T> T getBean(Class<T> requiredType) throws BeansException {this.assertBeanFactoryActive();return this.getBeanFactory().getBean(requiredType);}
    public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {this.assertBeanFactoryActive();return this.getBeanFactory().getBean(requiredType, args);}
    public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {this.assertBeanFactoryActive();return this.getBeanFactory().getBeanProvider(requiredType);}
    public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {this.assertBeanFactoryActive();return this.getBeanFactory().getBeanProvider(requiredType);}
    public boolean containsBean(String name) {return this.getBeanFactory().containsBean(name);}
    public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {this.assertBeanFactoryActive();return this.getBeanFactory().isSingleton(name);}
    public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {this.assertBeanFactoryActive();return this.getBeanFactory().isPrototype(name);}

Kami mendapati bahawa memanggil kacang yang disuntik dalam kaedah Ujian statik secara langsung melaporkan ralat : Terima kasih kepada kelas Menurut mekanisme pemuatan dan susunan, sifat statik dan blok kod statik dimuatkan terlebih dahulu (statik diutamakan tidak ada contoh kacang untuk anda memuatkan kaedah statik di sini, jadi ralat secara semula jadi akan dilaporkan).

Bagaimana untuk menyelesaikannya? Kita boleh menerima pakai idea memanggil kaedah getBean apabila Spring memperoleh objek kacang, dan secara statik menyimpan konteks bekas spring apabila bekas dimuatkan:

public class JsonGetter {
@Resource
private UuidGetter uuidGetter;
public static string Test(){
       return uuidGetter.getUuid();
}
public static JsONobject set0bjectToJsonObject(object data){
       return JsoNobject.parseObject(String.valueof(JsONObject.toJSON(data)));
}
public static JsONObject setStringTO3son0bject(String data) { return JsONObject.parseObject(data);
}

Perkara yang hanya perlu kita perhatikan di sini ialah takrifan, penugasan dan pengesahan pembolehubah ahli statik ApplicationContext :

@Component
@Lazy(value = false)
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
    /**
     * 将上下文静态设置,在初始化组件时就进行静态上下文的覆盖(这个覆盖是将远spring容器的上下文对象引用加到我们预定设置)
     */
    private static ApplicationContext applicationContext = null;
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }
    public static  <T> T getBean(Class<T> beanType) {
        assertContextInjected();
        return applicationContext.getBean(beanType);
    }
    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }
    @Override
    public void destroy() {
        applicationContext = null;
    }
    private static void assertContextInjected() {
        Assert.notNull(applicationContext,
                "applicationContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
    }
    public static void pushEvent(ApplicationEvent event){
        assertContextInjected();
        applicationContext.publishEvent(event);
    }
}

Tulis semula kaedah antara muka lanjutan untuk mencapai liputan konteks statik:

    /**
     * 将上下文静态设置,在初始化组件时就进行静态上下文的覆盖(这个覆盖是将远spring容器的上下文对象引用加到我们预定设置)
     */
    private static ApplicationContext applicationContext = null;

Ubah suai kaedah untuk mendapatkannya secara terbuka untuk memudahkan perkongsian:

    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }

Masih menulisnya di sini saya tidak faham, apakah peranan mentakrifkan komponen seperti ini dan mengatasi objek konteks spring secara statik?

Jangan panik, mari kita lihat kaedah kelas ini:

    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }

Kami mendapati bahawa operasi semakan perpustakaan telah dilakukan dalam kod contoh di atas:

public class AppContext {
    static transient ThreadLocal<Map<String, String>> contextMap = new ThreadLocal<>();
    ......省略n行业务代码
    public static void fillLoginContext() {
        DingAppInfo appInfo = SpringContextHolder.getBean(DingAppInfoService.class).findAppInfo(APP_CODE);
        setDingVerifyInfo(appInfo);
        CloudChatAppInfo cloudChatAppInfo = SpringContextHolder.getBean(CloudChatAppInfoService.class).findAppInfo(APP_CODE);
        setCloudChatInfo(cloudChatAppInfo);
    }
    public static void clear() {
        contextMap.remove(); //本地线程的remove方法极其重要,注意每次给它使用之后一定要调用remove清理,防止内存泄露。
    }
}

Atas ialah kandungan terperinci Cara menggunakan antara muka lanjutan SpringBoot ApplicationContextAware. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam