Conocimiento del contenedor SpringIoc | Equipo técnico de JD Cloud

1. Introducción

Aware es una superinterfaz de marcador proporcionada por Spring, que indica que el contenedor de Spring puede notificar el bean a un objeto de marco específico a través de un método de estilo de devolución de llamada para obtener uno de los métodos de una instancia de un objeto específico en el contenedor. La firma del método real está determinada por las subinterfaces individuales, pero generalmente consiste solo en un método de devolución de vacío que acepta un solo parámetro.

2 Implementaciones integradas de Nine Aware en Spring

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



Las 9 implementaciones integradas se dividen en dos categorías, las primeras tres son llamadas directas y las últimas 6 son devoluciones de llamada indirectas a través de los postprocesadores 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 la interfaz BeanNameAware, debe implementar el método setBeanName(). Este método simplemente devuelve nuestro beanName actual. La función superficial de esta interfaz es permitir que el bean que implementa esta interfaz conozca su nombre en el contenedor de primavera, y el oficial El significado es esta interfaz. Se usa más en el código marco de Spring, y no debería recomendarse en el entorno de desarrollo real, porque Spring piensa que el nombre del bean no está muy conectado con el bean (de hecho, aparte de la API de primavera, si obtenemos el bean El nombre del bean en realidad no es muy significativo. No hemos obtenido la clase del bean, solo el nombre del bean, y no tenemos forma de comenzar. Al contrario, porque el nombre del bean puede ser el identificador único del bean en el contenedor spring, es decir, en beanDefinitionMap, el valor clave es el nombre, y spring puede obtener todas las características del bean según este valor clave), entonces Spring dice que esta no es una dependencia innecesaria.

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);

}



Proporciona devoluciones de llamada para modificadores de clase después de que se completen las propiedades del bean pero antes de la inicialización. Deje que el propio bean administrado sepa qué tipo de cargador es responsable de cargar.

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;

}



Devolución de llamada a la fábrica de beans después de que se completen las propiedades del bean y antes de la inicialización. Un bean que implemente la interfaz BeanFactoηAware puede acceder directamente al contenedor Spring.Después de ser creado por el contenedor, tendrá una referencia al contenedor Spring, que se puede usar para obtener dinámicamente el bean cargado por la fábrica Spring de acuerdo con los parámetros entrantes. .

2.4 Consciente del Medio Ambiente

public interface EnvironmentAware extends Aware {

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

}



Establece el objeto en el que se ejecutará. Para todos los beans registrados en el contenedor Spring, siempre que el bean implemente la interfaz EnvironmentAware y reescriba el método setEnvironment, los valores de propiedad configurados en el archivo de configuración application.properties se pueden obtener cuando se inicia el proyecto, de modo que No necesitamos que escribamos el valor mágico en el código.

2.5 Resolver valores integrados

public interface EmbeddedValueResolverAware extends Aware {

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

}



Al obtener el valor del atributo del archivo de propiedades basado en Spring, el método @Value generalmente se usa para inyectar el valor del atributo del archivo de configuración, pero @Value debe usarse bajo la administración del ciclo de vida de Bean de Spring, como la clase que se está @Controller, @Service, @Component, etc. anotaciones. Por ejemplo, en algunas clases abstractas, use EmbeddedValueResolverAware para analizar los archivos de configuración según la forma en que Spring analiza @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 es la interfaz de marcador especial que espera tener un objeto referenciado por un ResourceLoader. Cuando una clase que implementa la interfaz ResourceLoaderAware se implementa en el contexto de la aplicación (como un bean administrado por Spring), el contexto de la aplicación la reconocerá como ResourceLoaderAware. Luego, el contexto de la aplicación llamará al método setResourceLoader(ResourceLoader) y se pasará como parámetro al método (recuerde, todos los contextos de la aplicación en Spring implementan la interfaz ResourceLoader).

Dado que ApplicationContext es ResourceLoader, el bean puede implementar la interfaz ApplicationContextAware y usar directamente el contexto de la aplicación proporcionado para cargar recursos, pero generalmente es más adecuado usar una implementación específica de ResourceLoader que satisfaga todas las necesidades. De esta manera, el código solo necesita depender de la interfaz de carga de recursos, que puede considerarse como una interfaz auxiliar, en lugar de depender de toda la interfaz Spring ApplicationContext.

2.7 ApplicationEventPublisherAware

public interface ApplicationEventPublisherAware extends Aware {

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

}



ApplicationEventPublisherAware es una interfaz proporcionada por Spring para inyectar el editor de eventos ApplicationEventPublisher en el Servicio. Usando esta interfaz, nuestro propio Servicio tiene la capacidad de publicar eventos.

2.8 Consciente de la fuente del mensaje

public interface MessageSourceAware extends Aware {

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

}



Obtenga la fuente del mensaje para que pueda obtener la información de texto, y el escenario de uso es para la internacionalización.

2.9 Conocimiento del contexto de la aplicación

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;

}



La función de ApplicationContextAware es obtener fácilmente el ApplicationContext del contenedor Spring, de modo que se pueda obtener el Bean en el contenedor. La interfaz ApplicationContextAware solo tiene un método. Si se implementa este método, Spring ejecutará automáticamente este método al crear la clase de implementación e inyectará ApplicationContext en esta clase. Es decir, Spring necesita instanciar esta clase cuando se inicia (si es de carga diferida, se crea una instancia cuando lo necesita). Al crear una instancia de esta clase, si encuentra que contiene la interfaz ApplicationContextAware, sping llamará al método setApplicationContext de este objeto y colocará el conjunto applicationContext en él.

3 Duración de las llamadas en primavera

Spring activa la interfaz de Aware en el método AbstractAutowireCapableBeanFactory.initializeBean(beanName, bean, mbd) al llamar al método de InvoqueAwareMethods(beanName, bean) y applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName) para activar la invocación del método Aware.

3.1 métodos de invocación conscientes

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);
      }
   }
}



Juicio y devolución de llamada directa

3.2 aplicarBeanPostProcessorsBeforeInitialization

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;
}



Se invoca indirectamente a través de ApplicationContextAwareProcessor.postProcessBeforeInitialization(Object bean, String beanName) y se invoca de nuevo en el 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 Resumen

A través del análisis anterior, podemos saber que en el método de inicialización en el ciclo de vida de Spring, antes de que se ejecute realmente el método de inicialización, la llamada a Aware es activada por el método invoqueAwareMethods y el postprocesador ApplicationContextAwareProcessor respectivamente.Entonces, ¿por qué Spring usa dos métodos en lugar de ¿Qué hay de usar uno de ellos?

A lo largo de este capítulo, hemos aprendido sobre las funciones de las interfaces integradas en 9 y la diferente información contextual que pueden obtener.

Autor: JD Retail Zeng Dengjun

Fuente: Comunidad de desarrolladores de JD Cloud

Los graduados de la Universidad Popular Nacional robaron la información de todos los estudiantes de la escuela para construir un sitio web de puntuación de belleza, y han sido detenidos criminalmente.La nueva versión de Windows de QQ basada en la arquitectura NT se lanza oficialmente.Estados Unidos restringirá el uso de China de Amazon, Microsoft y otros servicios en la nube que brindan capacitación en modelos de IA. Se anunciaron proyectos de código abierto para detener el desarrollo de funciones LeaferJS , el puesto técnico mejor pagado en 2023, lanzado: Visual Studio Code 1.80, una biblioteca de gráficos 2D de código abierto y potente , compatible funciones de imagen de terminal . El número de registros de subprocesos ha superado los 30 millones. "Cambio" deepin adopta Asahi Linux para adaptarse a la clasificación de la base de datos Apple M1 en julio: Oracle aumenta, abriendo el puntaje nuevamente
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

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