Ciente do contêiner SpringIoc | Equipe técnica do JD Cloud

1. Introdução

Aware é uma superinterface de marcador fornecida pelo Spring, indicando que o bean é elegível para ser notificado pelo contêiner Spring para um objeto de estrutura específico por meio de um método estilo callback para obter um dos métodos de uma instância de um objeto específico no contêiner. A assinatura do método real é determinada pelas subinterfaces individuais, mas geralmente consiste apenas em um método de retorno nulo que aceita um único parâmetro.

2 Implementações integradas do Nine Aware no Spring

|--Aware
    |--BeanNameAware
    |--BeanClassLoaderAware
    |--BeanFactoryAware
    |--EnvironmentAware
    |--EmbeddedValueResolverAware
    |--ResourceLoaderAware
    |--ApplicationEventPublisherAware
    |--MessageSourceAware
    |--ApplicationContextAware



As 9 implementações integradas são divididas em duas categorias, as três primeiras são chamadas diretas e as últimas 6 são callbacks indiretos por meio de pós-processadores ApplicationContextAwareProcessor

2.1 BeanNameAware

public interface BeanNameAware extends Aware {

       /**
        *设置创建此bean的bean工厂中的bean的名称。
        *在普通bean属性填充之后但在
        *初始化之前回调,如{@link InitializingBean#afterPropertiesSet()}
        *或自定义初始化方法。
        * @param name工厂中bean的名称。
        *注意,此名称是工厂中使用的实际bean名称,这可能
        *与最初指定的名称不同:特别是对于内部bean
        * names,实际的bean名称可以通过添加
        *“#…”后缀。使用{@link BeanFactoryUtils#originalBeanName(String)}
        *方法提取原始bean名称(不带后缀),如果需要的话。
        * /
	void setBeanName(String name);

}



Para implementar a interface BeanNameAware, você precisa implementar o método setBeanName(). Este método simplesmente retorna nosso beanName atual. O papel superficial desta interface é permitir que o bean que implementa esta interface saiba seu nome no container spring, e o oficial o significado é esta interface É mais usado no código da estrutura do spring, e o ambiente de desenvolvimento real não deve ser recomendado, porque o spring pensa que o nome do bean não está profundamente conectado com o bean (de fato, além da API do spring , se obtivermos o bean O nome do bean na verdade não é muito significativo. Não obtivemos a classe do bean, apenas o nome do bean e não temos como começar. Pelo contrário, porque o nome de o bean pode ser o identificador único do bean no contêiner do spring, ou seja, no beanDefinitionMap, o valor da chave é o nome, e o spring pode obter todas as características do bean de acordo com esse valor da chave), então spring diz que esta não é uma dependência desnecessária.

2.2 BeanClassLoaderAware

public interface BeanClassLoaderAware extends Aware {

   /**
    *提供bean {@link ClassLoader}类加载器的回调
    *一个bean实例在属性的填充之后但在初始化回调之前调用
    * {@link InitializingBean
    * {@link InitializingBean#afterPropertiesSet()}
    *方法或自定义初始化方法。
    * @param类加载器拥有的类加载器;可能是{@code null}在例如,必须使用默认的{@code ClassLoader}
    * 获取的{@code ClassLoader}
    * {@link org.springframework.util.ClassUtils#getDefaultClassLoader()}
    * /
   void setBeanClassLoader(ClassLoader classLoader);

}



Fornece retornos de chamada para modificadores de classe depois que as propriedades do bean são preenchidas, mas antes da inicialização. Deixe o próprio bean gerenciado saber qual tipo de carregador ele é responsável por carregar.

2.3 BeanFactoryAware

public interface BeanFactoryAware extends Aware {

   /**
    * 为bean实例提供所属工厂的回调。
    * 在普通bean属性填充之后调用但在初始化回调之前,如
    * {@link InitializingBean#afterPropertiesSet()}或自定义初始化方法。
    * @param beanFactory拥有beanFactory(非空)。bean可以立即调用工厂上的方法。
    * @在初始化错误时抛出BeansException
    * @参见BeanInitializationException
    * /
   void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}



Retorno de chamada para a fábrica de bean depois que as propriedades do bean são preenchidas e antes da inicialização. Um bean que implementa a interface BeanFactoηAware pode acessar diretamente o contêiner Spring. Após ser criado pelo contêiner, ele terá uma referência ao contêiner Spring, que pode ser usada para obter dinamicamente o bean carregado pela fábrica de primavera de acordo com os parâmetros recebidos .

2.4 Consciente do meio ambiente

public interface EnvironmentAware extends Aware {

   /**
    * 设置该对象运行的{@code环境}。
    */
   void setEnvironment(Environment environment);

}



Define o objeto a ser executado. Para todos os beans registrados no contêiner Spring, desde que o bean implemente a interface EnvironmentAware e reescreva o método setEnvironment, os valores de propriedade configurados no arquivo de configuração application.properties podem ser obtidos quando o projeto é iniciado, para que não precisamos escrever o valor mágico no código.

2.5 EmbeddedValueResolverAware

public interface EmbeddedValueResolverAware extends Aware {

   /**
    * 设置StringValueResolver用于解析嵌入的定义值。
    */
   void setEmbeddedValueResolver(StringValueResolver resolver);

}



Ao obter o valor do atributo do arquivo de propriedades com base no Spring, o método @Value geralmente é usado para injetar o valor do atributo do arquivo de configuração, mas @Value deve ser usado sob o gerenciamento do ciclo de vida Bean do Spring, como a classe que está sendo @Controller, @Service, @Component etc. Por exemplo, em algumas classes abstratas, use EmbeddedValueResolverAware para analisar arquivos de configuração com base na maneira como o Spring analisa @Value.

2.6 ResourceLoaderAware

public interface ResourceLoaderAware extends Aware {

   /**
    *设置该对象运行的ResourceLoader。这可能是一个ResourcePatternResolver,它可以被检查
    *通过{@code instanceof ResourcePatternResolver}。另请参阅
    * {@code ResourcePatternUtils。getResourcePatternResolver}方法。
    * <p>在填充普通bean属性之后但在init回调之前调用
    *像InitializingBean的{@code afterPropertiesSet}或自定义初始化方法。
    *在ApplicationContextAware的{@code setApplicationContext}之前调用。
    * @param resourceLoader该对象使用的resourceLoader对象
    * @ @ springframework.core. io.support.resourcepatternresolver
    * @ @ resourcepatternutils #获取resourcepatternresolver
    * /
   void setResourceLoader(ResourceLoader resourceLoader);

}



ResourceLoaderAware é a interface de marcador especial que espera ter um objeto referenciado por um ResourceLoader. Quando uma classe que implementa a interface ResourceLoaderAware é implantada no contexto do aplicativo (como um bean gerenciado pelo Spring), ela será reconhecida como ResourceLoaderAware pelo contexto do aplicativo. Em seguida, o contexto do aplicativo chamará o método setResourceLoader(ResourceLoader) e se passará como um parâmetro para o método (lembre-se de que todos os contextos de aplicativo no Spring implementam a interface ResourceLoader).

Como o ApplicationContext é o ResourceLoader, o bean pode implementar a interface ApplicationContextAware e usar diretamente o contexto do aplicativo fornecido para carregar recursos, mas geralmente é mais adequado usar uma implementação específica do ResourceLoader que atenda a todas as necessidades. Dessa forma, o código precisa depender apenas da interface de carregamento de recursos, que pode ser considerada uma interface auxiliar, em vez de depender de toda a interface Spring ApplicationContext.

2.7 ApplicationEventPublisherAware

public interface ApplicationEventPublisherAware extends Aware {

   /**
    *设置该对象运行的ApplicationEventPublisher。
    * <p>在普通bean属性填充之后但在init之前调用像InitializingBean的afterPropertiesSet或自定义初始化方法。
    *在ApplicationContextAware的setApplicationContext之前调用。
    *该对象使用的事件发布者
    * /
   void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher);

}



ApplicationEventPublisherAware é uma interface fornecida pelo Spring para injetar o publicador de eventos ApplicationEventPublisher no Serviço. Usando esta interface, nosso próprio Serviço tem a capacidade de publicar eventos.

2.8 MessageSourceAware

public interface MessageSourceAware extends Aware {

   /**
    *设置该对象运行的MessageSource。
    * <p>在普通bean属性填充之后但在init之前调用像InitializingBean的afterPropertiesSet或自定义初始化方法。
    *在ApplicationContextAware的setApplicationContext之前调用。
    * @param messageSource消息源
    * /
   void setMessageSource(MessageSource messageSource);

}



Obtenha a origem da mensagem para obter as informações de texto e o cenário de uso é para internacionalização.

2.9 ApplicationContextAware

public interface ApplicationContextAware extends Aware {

   /**
    *设置该对象运行的ApplicationContext。通常这个调用将用于初始化对象。
    * <p>在普通bean属性填充之后但在init回调之前调用
    *作为{@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
    *或自定义初始化方法。在{@link ResourceLoaderAware#setResourceLoader}之后调用,
    * {@link ApplicationEventPublisherAware#setApplicationEventPublisher}和
    * {@link MessageSourceAware},如果适用。
    * @param applicationContext该对象将使用的applicationContext对象
    * @在上下文初始化错误时抛出ApplicationContextException如果由应用程序上下文方法抛出,则抛出BeansException
    * @see org.springframework.beans.factory.BeanInitializationException
    * /
   void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}



O papel do ApplicationContextAware é obter facilmente o ApplicationContext do contêiner Spring, para que o Bean no contêiner possa ser obtido. A interface ApplicationContextAware possui apenas um método. Se este método for implementado, o Spring executará automaticamente este método ao criar a classe de implementação, e injetará o ApplicationContext nesta classe. Ou seja, o Spring precisa instanciar esta classe quando iniciar (Se é carregamento lento, é instanciado quando você precisa usá-lo) Ao instanciar esta classe, se descobrir que contém a interface ApplicationContextAware, o sping chamará o método setApplicationContext deste objeto e colocará o conjunto applicationContext nele.

3 Tempo de chamada na primavera

A interface Aware é acionada pelo Spring no método AbstractAutowireCapableBeanFactory.initializeBean(beanName, bean, mbd) chamando o método invokeAwareMethods(beanName, bean) e applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName) para acionar a invocação do método Aware

3.1 invocarAwareMethods

private void invokeAwareMethods(final String beanName, final Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
         ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
      }
      if (bean instanceof BeanFactoryAware) {
         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
   }
}



Julgamento e callback direto

3.2 applyBeanPostProcessorsBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      result = beanProcessor.postProcessBeforeInitialization(result, beanName);
      if (result == null) {
         return result;
      }
   }
   return result;
}



Ele é chamado indiretamente por meio de ApplicationContextAwareProcessor.postProcessBeforeInitialization(Object bean, String beanName) e é chamado de volta no método invokeAwareInterfaces.

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
   AccessControlContext acc = null;

   if (System.getSecurityManager() != null &&
         (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
               bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
               bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
      acc = this.applicationContext.getBeanFactory().getAccessControlContext();
   }

   if (acc != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
         @Override
         public Object run() {
            invokeAwareInterfaces(bean);
            return null;
         }
      }, acc);
   }
   else {
      invokeAwareInterfaces(bean);
   }

   return bean;
}

private void invokeAwareInterfaces(Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof EnvironmentAware) {
         ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {
         ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
               new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
      }
      if (bean instanceof ResourceLoaderAware) {
         ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {
         ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {
         ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {
         ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
   }
}



4 Resumo

Através da análise acima, podemos saber que no método de inicialização no ciclo de vida do Spring, antes que o método de inicialização seja realmente executado, a chamada Aware é acionada pelo método invokeAwareMethods e o pós-processador ApplicationContextAwareProcessor, respectivamente. Então, por que o Spring usa dois métodos em vez de Que tal usar um deles?

Neste capítulo, aprendemos sobre as funções das interfaces integradas no 9 e as diferentes informações contextuais que elas podem obter.

Autor: JD Retail Zeng Dengjun

Fonte: JD Cloud Developer Community

Os graduados da National People's University roubaram as informações de todos os alunos da escola para criar um site de pontuação de beleza e foram detidos criminalmente. A nova versão do QQ para Windows baseada na arquitetura NT é lançada oficialmente. Os Estados Unidos restringirão o uso da China da Amazon, Microsoft e outros serviços em nuvem que fornecem modelos de IA de treinamento . Projetos de código aberto anunciados para interromper o desenvolvimento de funções LeaferJS , a posição técnica mais bem paga em 2023, lançou : Visual Studio Code 1.80, uma poderosa biblioteca de gráficos 2D de código aberto funções de imagem de terminal . O número de registros de Threads ultrapassou 30 milhões. "Change" deepin adota Asahi Linux para se adaptar ao ranking de banco de dados Apple M1 em julho: Oracle surge, abrindo o placar novamente
{{o.name}}
{{m.nome}}

Acho que você gosta

Origin my.oschina.net/u/4090830/blog/10086653
Recomendado
Clasificación