Heim > Web-Frontend > js-Tutorial > Detaillierte Erläuterung des Spring-Lebenszyklus und der Verwendung von Containererweiterungen

Detaillierte Erläuterung des Spring-Lebenszyklus und der Verwendung von Containererweiterungen

php中世界最好的语言
Freigeben: 2018-04-13 14:45:18
Original
1762 Leute haben es durchsucht

Dieses Mal werde ich Ihnen eine detaillierte Erklärung der Verwendung von Spring--Lebenszyklus-- und Container-Erweiterungen geben. Was sind die Vorsichtsmaßnahmen bei der Verwendung von Spring-Lebenszyklus- und Container-Erweiterungen? ? Das Folgende sind praktische Fälle, schauen wir uns das an.

Das Folgende ist die Haupteinleitung:

Konfiguration der Rückrufmethode für die Initialisierung des Lebenszyklus auf Klassenebene, Konfiguration der Init-Methode, InitializingBean-Schnittstelle und PostConstruct-Annotation

Erweiterte BeanPostProcessor-Schnittstelle und BeanFactoryPostProcessor-Schnittstelle auf Containerebene

1. Rückruf des Lebenszyklus auf Klassenebene

1.1init-Methode

Referenz: Springbeanxsdinit-method

init-method ist ein Konfigurationselement beim Deklarieren einer Bean in der Spring--Konfigurationsdatei . Der Wert des Konfigurationselements „init-method“ ist eine Methode ohne Parameter in der Klasse, kann jedoch eine Ausnahme auslösen . Diese Methode wird aufgerufen, nachdem der Spring-Container das Objekt instanziiert und die Eigenschaftswerte festgelegt hat.

Die Funktionen, die die Init-Methode implementieren kann, stimmen mit der InitializingBean-Schnittstelle und den PostConstruct-Annotationen

überein Die Spring-Konfigurationsdateien und Testklassen lauten wie folgt:

<bean id = "initMethodBeanService" class="name.liuxi.spring.ext.InitMethodBeanService" init-method="init">
   <property name="f2" value="2"/>
</bean>
Nach dem Login kopieren

Die Testklassen sind wie folgt:

public class InitMethodBeanService {
	private static Integer f1;
	private Integer f2;
	static {
		f1 = 1;
		System.out.println("InitMethodBeanService static block execute...");
	}
	public InitMethodBeanService(){
		System.out.println("InitMethodBeanService construct method execute...");
	}
	public void init(){
		System.out.println("InitMethodBeanService init method execute...");
	}
	public Integer getF2() {
		return f2;
	}
	public void setF2(Integer f2) {
		this.f2 = f2;
		System.out.println("InitMethodBeanService setF2 method execute...");
	}
}
Nach dem Login kopieren

Das Ausführungsergebnis wird wie folgt gedruckt:

InitMethodBeanService static block execute...
InitMethodBeanService construct method execute...
InitMethodBeanService setF2 method execute...
InitMethodBeanService init method execute...
test method execute...
Nach dem Login kopieren

1.2Bean-Schnittstelle initialisieren

Referenz: Offizielles Frühlingsdokument beans-factory-lifecycle-initializingbean

Die InitializingBean-Schnittstelle deklariert eine Methode afterPropertiesSet, die aufgerufen wird, nachdem der Spring-Container das Objekt instanziiert und die Eigenschaftswerte festlegt. Die von der oben genannten init-Methode implementierte Funktion ist konsistent, daher empfiehlt Spring nicht, die InitializingBean-Schnittstelle zu verwenden.

Das Beispiel ist relativ einfach und wird hier nicht aufgeführt

1.3PostConstruct-Anmerkung

Übersetzung: Offizielles Frühlingsdokument Beans-Postconstruct-and-Predestroy-Annotations

Die Annotation @PostConstruct ist eine Rückrufmethode für den Lebenszyklus, die den gleichen Effekt hat wie die Schnittstellen init-method und InitializingBean

@PostConstruct
public void postConstruct(){
  System.out.println("PostConstructService postConstruct method execute...");
}
Nach dem Login kopieren

Fassen Sie die oben genannten drei Lebenszyklus-Rückrufmethoden zusammen: Init-Methode, InitializingBean-Schnittstelle und @PostConstruct-Annotation

1. Sie werden alle nach der Instanziierung für eine einzelne Klasse verarbeitet

2. Die gesamte Ausführungszeit wird aufgerufen, nachdem die Klasse instanziiert und die Mitgliedsvariablen eingefügt wurden

3. Für die Init-Methode können Sie auch die Standardinitialisierungsmethode unter dem Beans-Element der Spring-Konfigurationsdatei konfigurieren. Das Konfigurationselement ist default-init-method

4. Wenn die auf die oben genannten drei Arten konfigurierten Initialisierungsmethoden unterschiedlich sind, lautet die Ausführungsreihenfolge: @PostConstruct-Annotationsmethode –>InitializingBean's afterPropertiesSet–>init-method-Methode; wenn die auf drei Arten konfigurierten Methoden gleich sind Methoden werden nur einmal ausgeführt (siehe: Offizielles Spring-Dokument „Beans-Factory-Lifecycle-Combined-Effect“)

5. Es gibt eine Initialisierungs-Rückrufmethode und eine entsprechende Zerstörungs-Rückrufmethode. Die @PostConstruct-Annotationsmethode –>InitializingBeans afterPropertiesSet–>init-method-Methode entspricht jeweils der @PreDestroy-Annotationsmethode –>DisposableBeans destroy–>destroy-method-Methode

2. Erweiterung der Containerebene

Übersetzung: Offizielles Frühlingsdokument 3.8ContainerExtensionPoints

Unter normalen Umständen müssen Entwickler keine Unterklasse von ApplicationContext anpassen, um den SpringIOC-Container zu erweitern. Der SpringIOC-Container kann den SpringIOC-Container über einige extern verfügbar gemachte Schnittstellen erweitern.

2.1BeanPostProcessor-Schnittstelle

2.1.1Bean-Instanz-Initialisierungs-Postprozessor und Postprozessorkette

Die BeanPostProcessor-Schnittstelle definiert zwei Rückrufmethoden auf Containerebene, postProcessBeforeInitialization und postProcessAfterInitialization, die für einige logische Verarbeitungen nach der Initialisierung der Instanz verwendet werden und für alle Instanzen im Container verarbeitet werden. Die Klasse, die die BeanPostProcessor-Schnittstelle implementiert, wird als Postprozessor für die Initialisierung der Bean-Instanz bezeichnet.

Wenn mehrere Instanzinitialisierungs-Postprozessoren in den Spring IOC-Container integriert sind, wird die Sammlung dieser Postprozessoren als Postprozessorkette für die Bean-Instanzinitialisierung bezeichnet.

postProcessBeforeInitialization方法在类实例化且成员变量注入完成之后执行,初始化方法(例如InitializingBean的afterPropertiesSet方法)之前执行

postProcessAfterInitialization方法在类实例化且成员变量注入完成之后执行,初始化方法(例如InitializingBean的afterPropertiesSet方法)之后执行

总结:

1.实例初始化后处理器多用于对实例的一些代理操作。Spring中一些使用到AOP的特性也是通过后处理器的方式实现的。

2.实例初始化后处理器链是多个后处理器,就会有执行顺序的问题,可以通过实现Ordered接口,指定后处理的执行顺序,Ordered接口声明了getOrder方法,方法返回值越小,后处理的优先级越高,越早执行。

3.在通过实现BeanPostProcessor接口自定义实例初始化后处理器的时候,建议也实现Ordered接口,指定优先级。

4.这些后处理器的作用域是当前的SpringIOC容器,即后处理器被声明的SpringIOC容器。对于有层次结构的SpringIOC容器,实例初始化后处理器链不会作用于其他容器所初始化的实例上,即使两个容器在同一层次结构上。

5.实例初始化后处理器的实现类只需要和普通的被Spring管理的bean一样声明,SpringIOC容器就会自动检测到,并添加到实例初始化后处理器链中。

6.相对于自动检测,我们也可以调用ConfigurableBeanFactory的addBeanPostProcessor方法,以编程的方式将一个实例初始化后处理器添加到实例初始化后处理器链中。这在需要判定添加条件的场景下比较实用。这种编程式的方式会忽略到实现的Ordered接口所指定的顺序,而会作用于所有的被自动检测的实例初始化后处理器之前。

2.1.2bean实例初始化后处理器与AOP

BeanPostProcessor是一个特殊的接口,实现这个接口的类会被作为Spring管理的bean的实例的后处理器。因此,在Spring应用上下文启动的一个特殊阶段,会直接初始化所有实现了BeanPostProcessor接口的实例,以及该实例所引用的类也会被实例化。然后作为后处理器应用于其他普通实例。

由于AOP的自动代理是以实例化后处理器的方式实现的,所以无论是bean实例初始化后处理器链实例还是其引用的实例,都不能被自动代理。因而,不要在这些实例上进行切面织入。(对于这些实例,会产生这样的日志消息:“类foo不能被所有的实例化后处理器链处理,即不能被自动代理”)。

注意:当实例化后处理器以autowiring或@Resource的方式引用其他bean,Spring容器在以类型匹配依赖注入的时候,可能会注入非指定的bean(例如:实例化后处理器实现类以Resource方式依赖bean,若set方法和被依赖的bean的名称一致或者被依赖bean未声明名称,则依赖注入会以类型匹配的方式注入,此时可能会注入非指定的bean)。这也会导致自动代理或其他方式的实例化后处理器处理失败。

2.1.3bean实例初始化后处理器示例

public class BeanPostProcessorService implements BeanPostProcessor {
	@Override
	  public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
		System.out.println("BeanPostProcessorService postProcessAfterInitialization method execute... ");
		return o;
	}
	@Override
	  public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
		System.out.println("BeanPostProcessorService postProcessBeforeInitialization method execute... ");
		return o;
	}
}
Nach dem Login kopieren

2.2BeanFactoryPostProcessor接口

2.2.1beanfactory后处理器

通过实现BeanFactoryPostProcessor接口,可以读取容器所管理的bean的配置元数据,在bean完成实例化之前进行更改,这些bean称之为beanfactory后处理器。

BeanFactoryPostProcessors与BeanPostProcessor接口的异同点:

相同点:

都是容器级别的后处理器

都可配置多个后处理器,并通过实现Ordered接口,指定执行顺序

都是针对接口声明的容器中所管理的bean进行处理,在有层级结构的容器中,不能处理其他容器中的bean,即使两个容器是同一层次

都是只需要在容器中和普通bean一样声明,容器会自动检测到,并注册为后处理器

会忽略延迟初始化属性配置

不同点:

BeanFactoryPostProcessors接口在bean**实例化前处理bean的配置元数据,BeanPostProcessor接口在bean实例化后处理bean的实例**

BeanFactoryPostProcessors接口也能通过BeanFactory.getBean()方法获取bean的实例,这样会引起bean的实例化。由于BeanFactoryPostProcessors后处理器是在所有bean实例化之前执行,通过BeanFactory.getBean()方法会导致提前实例化bean,从而打破容器标准的生命周期,这样可能会引起一些负面的影响(例如:提前实例化的bean会忽略bean实例化后处理器的处理)。

2.2.2Spring内置及自定义beanfactory后处理器

Spring内置了一些beanfactory后处理器(例如:PropertyPlaceholderConfigurer和PropertyOverrideConfigurer)。同时也支持实现BeanFactoryPostProcessor接口,自定义beanfactory后处理器。下面说说Spring内置的两个后处理器和自定义后处理器。

PropertyPlaceholderConfigurer

Spring为了避免主要的XML定义文件的修改而引起的风险,提供了配置分离,可以将一些可能变更的变量配置到属性配置文件中,并在XML定义文件中以占位符的方式引用。这样,修改配置只需要修改属性配置文件即可。PropertyPlaceholderConfigurer用于检测占位符,并替换占位符为配置属性值。示例如下:

PropertyPlaceholderConfigurer通过jdbc.properties属性配置文件,在运行时,将dataSource这个bean中数据库相关信息的属性占位符替换成对应的配置值。

XML配置如下:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>
<bean id="dataSource" destroy-method="close"
    class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
</bean>
Nach dem Login kopieren

属性配置文件jdbc.properties如下:

jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root
Nach dem Login kopieren

PropertyPlaceholderConfigurer不仅支持属性配置文件的读取,也支持读取系统属性。通过systemPropertiesMode属性值可配置读取优先级。各种取值说明如下:

0:不读取系统属性

1:若引用的属性配置文件中未检索到对应占位符的配置,则读取系统属性。默认为1

2:先读取系统属性,再读取引用的属性配置文件。这种配置可能导致系统属性覆盖配置文件。

PropertyOverrideConfigurer

PropertyOverrideConfigurer类可以通过引用属性配置文件,直接给容器中的bean赋值。当一个bean的属性被多个PropertyOverrideConfigurer类实例赋值时,最后一个的值会覆盖前面的。

还是以上面给上面的dataSource的bean赋值为例:

PropertyOverrideConfigurer类对属性配置文件的引用使用一个新的方式,如下:

<context:property-override location="classpath:override.properties"/>
Nach dem Login kopieren

override.properties属性配置文件的属性的命名规则和上面不同(上面例子中需要保证属性名和占位符一致),命名规则是beanName.property

dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb
dataSource.username=sa
dataSource.password=root
Nach dem Login kopieren

支持复合属性的赋值,但是要保证引用被赋值属性的对象非空
例如:foo.fred.bob.sammy=123
自定义bean factory后处理器

自定义bean factory后处理器就是实现BeanFactoryPostProcessor接口,完成对Spring容器管理的bean的配置元数据进行修改。例如:修改类属性注入的值,示例如下:

定义一个用户类UserBean

public class UserBean {
	private String userName;
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
}
Nach dem Login kopieren

Spring XML配置文件配置用户类,并给用户名属性userName注入值haha

<bean class="name.liuxi.spring.ext.BeanFactoryPostProcessorService"/>
<bean id="user" class="name.liuxi.spring.ext.UserBean">
   <property name="userName" value="haha"/>
</bean>
Nach dem Login kopieren

下面是自定义的bean factory后处理器,修改属性userName的值为heihei

public class BeanFactoryPostProcessorService implements BeanFactoryPostProcessor {
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    System.out.println("BeanFactoryPostProcessorService postProcessBeanFactory method execut...");
    BeanDefinition bd = beanFactory.getBeanDefinition("user");
    MutablePropertyValues pv = bd.getPropertyValues();
    if(pv.contains("userName"))
    {
      pv.addPropertyValue("userName", "heihei");
    }
  }
}
Nach dem Login kopieren

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

AngularJS实现猜数字小游戏

vue实现键盘效果

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Spring-Lebenszyklus und der Verwendung von Containererweiterungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage