Maison > Java > javaDidacticiel > le corps du texte

Comment utiliser l'interface étendue SpringBoot ApplicationContextAware

王林
Libérer: 2023-05-15 17:04:06
avant
963 Les gens l'ont consulté

Interface ApplicationContextAware :

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
Copier après la connexion

Tout d'abord, l'interface Aware sait qu'il s'agit d'une extension Springboot que les utilisateurs peuvent utiliser. La méthode setApplicationContext est fournie ici. Le paramètre doit être transmis dans l'objet de contexte du conteneur Spring. object.Nous voulons savoir comment obtenir le conteneur spring.Quel est le rôle spécifique du contexteApplicationContextC'est le but de l'interface étendue d'obtenir le contexte et de faire quelque chose en fonction des caractéristiques du contexte.

Jetons un coup d'œil aux méthodes de l'objet ApplicationContext :

Comment utiliser linterface étendue SpringBoot ApplicationContextAware

Jetons un coup d'œil aux méthodes de la classe d'implémentation AbstractApplicationContext :

    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);}
Copier après la connexion

Ici, nous pouvons constater que la méthode getBean() semble familière, car nous Nous n'avons pas utilisé Spring lorsque nous avons appris Spring pour la première fois. Lors de la création d'un projet d'échafaudage, la façon dont nous obtenons le bean consiste généralement à analyser le fichier XML du bean avec classPathContextLoader et à l'analyser pour former un objet ApplicationCOntext, puis à appeler sa méthode getBean pour l'obtenir. le bean instance.

À partir de cela, nous pouvons constater que notre principale méthode d'application consiste à utiliser cette méthode getBean. Ensuite, nous pouvons injecter dynamiquement des beans via de nombreuses méthodes, il n'est donc pas difficile de penser au problème selon lequel les beans injectés ne peuvent pas être utilisés dans des méthodes statiques.

Ensuite, reproduisons ce problème. Jetons un œil au code suivant :

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);
}
Copier après la connexion

Nous avons constaté que l'appel du bean injecté dans la méthode statique Test signale directement une erreur : Grâce au mécanisme de chargement et de chargement. Dans l'ordre de la classe, les attributs statiques et les blocs de code statiques sont chargés en premier (le statique est prioritaire). Il n'y a pas d'instance de bean pour que vous puissiez charger des méthodes statiques ici, donc une erreur sera naturellement signalée.

Comment le résoudre ? Nous pouvons adopter l'idée d'appeler la méthode getBean lorsque Spring obtient l'objet bean, et stocker statiquement le contexte du conteneur Spring lorsque le conteneur est chargé :

@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);
    }
}
Copier après la connexion

Ce à quoi nous devons seulement faire attention ici est la définition, affectation et vérification de la variable membre statique ApplicationContext :

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

Réécrire la méthode de l'interface étendue pour obtenir une couverture de contexte statique :

    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }
Copier après la connexion

Rendre publique la méthode d'obtention et faciliter son partage :

    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }
Copier après la connexion

Je ne le fais toujours pas Je ne comprends pas après avoir écrit ceci, quel est l'intérêt de définir un composant de cette manière pour remplacer statiquement l'objet de contexte Spring. Que fait-il ?

Pas de panique, jetons un œil à cette méthode de cette classe :

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清理,防止内存泄露。
    }
}
Copier après la connexion

Nous avons constaté que l'opération de vérification de la bibliothèque a été effectuée dans l'exemple de code ci-dessus :

DingAppInfo appInfo = SpringContextHolder.getBean(DingAppInfoService.class).findAppInfo(APP_CODE);
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal