今天我们将研究春豆生命周期。 [春豆]( / 社区 / 教程 / 春豆 - 例子 - 教程 "春豆容器和春豆示例教程")是任何春豆应用程序中最重要的部分。
春豆生命周期
Spring Context is also responsible for injection dependencies in the bean, either through setter or constructor methods or by spring autowiring. Sometimes we want to initialize resources in the bean classes, for example creating database connections or validating third party services at the time of initialization before any client request. Spring framework provide different ways through which we can provide post-initialization and pre-destroy methods in a spring bean life cycle.
- 通过实施 InitializingBean和 DisposableBean界面 - 这些界面都宣布一个单一的方法,我们可以初始化/关闭豆中的资源。 对于后始化,我们可以实施
InitializingBean
界面,并提供afterPropertiesSet()
方法的实现。 为了预销,我们可以实施DisposableBean
界面,并提供destroy()
方法的实现。 这些方法是召回方法,类似于服务器听众的实现。 这种方法很简单,但不建议使用,因为它会在我们的豆实施中与 Spring 框架建立紧密的连接( _2)。 提供 -method和 destroy-method属性值在春豆配置文件中。 这是建议的方法,
请注意,无论是 post-init 方法还是 pre-destroy 方法都应该没有参数,但它们可以抛出例外,我们还需要从这些方法召唤的春季应用程序背景中获取豆类实例。
春豆生命周期 - @PostConstruct, @PreDestroy 注释
Spring framework also support @PostConstruct
and @PreDestroy
annotations for defining post-init and pre-destroy methods. These annotations are part of javax.annotation
package. However for these annotations to work, we need to configure our spring application to look for annotations. We can do this either by defining bean of type org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
or by context:annotation-config
element in spring bean configuration file. Let's write a simple Spring application to showcase the use of above configurations for spring bean life cycle management. Create a Spring Maven project in Spring Tool Suite, final project will look like below image.
春豆生命周期 - Maven 依赖
我们不需要包含任何额外的依赖性来配置春豆生命周期方法,我们的pom.xml文件就像任何其他标准的春豆项目一样。
1<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3 <groupId>org.springframework.samples</groupId>
4 <artifactId>SpringBeanLifeCycle</artifactId>
5 <version>0.0.1-SNAPSHOT</version>
6
7 <properties>
8
9 <!-- Generic properties -->
10 <java.version>1.7</java.version>
11 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
13
14 <!-- Spring -->
15 <spring-framework.version>4.0.2.RELEASE</spring-framework.version>
16
17 <!-- Logging -->
18 <logback.version>1.0.13</logback.version>
19 <slf4j.version>1.7.5</slf4j.version>
20
21 </properties>
22
23 <dependencies>
24 <!-- Spring and Transactions -->
25 <dependency>
26 <groupId>org.springframework</groupId>
27 <artifactId>spring-context</artifactId>
28 <version>${spring-framework.version}</version>
29 </dependency>
30 <dependency>
31 <groupId>org.springframework</groupId>
32 <artifactId>spring-tx</artifactId>
33 <version>${spring-framework.version}</version>
34 </dependency>
35
36 <!-- Logging with SLF4J & LogBack -->
37 <dependency>
38 <groupId>org.slf4j</groupId>
39 <artifactId>slf4j-api</artifactId>
40 <version>${slf4j.version}</version>
41 <scope>compile</scope>
42 </dependency>
43 <dependency>
44 <groupId>ch.qos.logback</groupId>
45 <artifactId>logback-classic</artifactId>
46 <version>${logback.version}</version>
47 <scope>runtime</scope>
48 </dependency>
49
50 </dependencies>
51</project>
春豆生命周期 - 模型类
让我们创建一个简单的Java豆类,用于服务类。
1package com.journaldev.spring.bean;
2
3public class Employee {
4
5 private String name;
6
7 public String getName() {
8 return name;
9 }
10
11 public void setName(String name) {
12 this.name = name;
13 }
14
15}
春豆生命周期 - InitializingBean, DisposableBean
让我们创建一个服务类,在那里我们将实现后启动和预破坏方法的界面。
1package com.journaldev.spring.service;
2
3import org.springframework.beans.factory.DisposableBean;
4import org.springframework.beans.factory.InitializingBean;
5
6import com.journaldev.spring.bean.Employee;
7
8public class EmployeeService implements InitializingBean, DisposableBean{
9
10 private Employee employee;
11
12 public Employee getEmployee() {
13 return employee;
14 }
15
16 public void setEmployee(Employee employee) {
17 this.employee = employee;
18 }
19
20 public EmployeeService(){
21 System.out.println("EmployeeService no-args constructor called");
22 }
23
24 @Override
25 public void destroy() throws Exception {
26 System.out.println("EmployeeService Closing resources");
27 }
28
29 @Override
30 public void afterPropertiesSet() throws Exception {
31 System.out.println("EmployeeService initializing to dummy value");
32 if(employee.getName() == null){
33 employee.setName("Pankaj");
34 }
35 }
36}
春豆生命周期 - 定制后起始,预破坏
由于我们不希望我们的服务有直接的春季框架依赖性,让我们创建另一种形式的员工服务类别,在那里我们将有春季生命周期后和预破坏的方法,我们将在春季豆配置文件中配置它们。
1package com.journaldev.spring.service;
2
3import com.journaldev.spring.bean.Employee;
4
5public class MyEmployeeService{
6
7 private Employee employee;
8
9 public Employee getEmployee() {
10 return employee;
11 }
12
13 public void setEmployee(Employee employee) {
14 this.employee = employee;
15 }
16
17 public MyEmployeeService(){
18 System.out.println("MyEmployeeService no-args constructor called");
19 }
20
21 //pre-destroy method
22 public void destroy() throws Exception {
23 System.out.println("MyEmployeeService Closing resources");
24 }
25
26 //post-init method
27 public void init() throws Exception {
28 System.out.println("MyEmployeeService initializing to dummy value");
29 if(employee.getName() == null){
30 employee.setName("Pankaj");
31 }
32 }
33}
在此之前,让我们创建另一个服务类,该类将使用 @PostConstruct 和 @PreDestroy 注释。
春豆生命周期 - @PostConstruct, @PreDestroy
下面是一个简单的类,将被配置为春豆,对于开始后和预破坏方法,我们正在使用 @PostConstruct 和 @PreDestroy 注释。
1package com.journaldev.spring.service;
2
3import javax.annotation.PostConstruct;
4import javax.annotation.PreDestroy;
5
6public class MyService {
7
8 @PostConstruct
9 public void init(){
10 System.out.println("MyService init method called");
11 }
12
13 public MyService(){
14 System.out.println("MyService no-args constructor called");
15 }
16
17 @PreDestroy
18 public void destory(){
19 System.out.println("MyService destroy method called");
20 }
21}
春豆生命周期 - 配置文件
让我们看看我们如何在春季背景文件中配置豆子。
1<?xml version="1.0" encoding="UTF-8"?>
2<beans xmlns="https://www.springframework.org/schema/beans"
3 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
5
6<!-- Not initializing employee name variable-->
7<bean name="employee" class="com.journaldev.spring.bean.Employee" />
8
9<bean name="employeeService" class="com.journaldev.spring.service.EmployeeService">
10 <property name="employee" ref="employee"></property>
11</bean>
12
13<bean name="myEmployeeService" class="com.journaldev.spring.service.MyEmployeeService"
14 init-method="init" destroy-method="destroy">
15 <property name="employee" ref="employee"></property>
16</bean>
17
18<!-- initializing CommonAnnotationBeanPostProcessor is same as context:annotation-config -->
19<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
20<bean name="myService" class="com.journaldev.spring.service.MyService" />
21</beans>
请注意,我不会在它的定义中初始化员工名称。由于EmployeeService正在使用界面,我们在这里不需要任何特殊的配置。对于MyEmployeeService Bean,我们正在使用 init-method 和 destroy-method 属性来让春节框架知道我们的自定义方法来执行。MyService bean 配置没有什么特别的,但正如你所看到的那样,我正在为此启用注释为基础的配置。我们的应用程序准备好了,让我们写一个测试程序来看看不同的方法如何执行。
春豆生命周期 - 测试计划
1package com.journaldev.spring.main;
2
3import org.springframework.context.support.ClassPathXmlApplicationContext;
4
5import com.journaldev.spring.service.EmployeeService;
6import com.journaldev.spring.service.MyEmployeeService;
7
8public class SpringMain {
9
10 public static void main(String[] args) {
11 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
12
13 System.out.println("Spring Context initialized");
14
15 //MyEmployeeService service = ctx.getBean("myEmployeeService", MyEmployeeService.class);
16 EmployeeService service = ctx.getBean("employeeService", EmployeeService.class);
17
18 System.out.println("Bean retrieved from Spring Context");
19
20 System.out.println("Employee Name="+service.getEmployee().getName());
21
22 ctx.close();
23 System.out.println("Spring Context Closed");
24 }
25
26}
当我们运行在测试程序上方时,我们会得到输出。
1Apr 01, 2014 10:50:50 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
2INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@c1b9b03: startup date [Tue Apr 01 22:50:50 PDT 2014]; root of context hierarchy
3Apr 01, 2014 10:50:50 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
4INFO: Loading XML bean definitions from class path resource [spring.xml]
5EmployeeService no-args constructor called
6EmployeeService initializing to dummy value
7MyEmployeeService no-args constructor called
8MyEmployeeService initializing to dummy value
9MyService no-args constructor called
10MyService init method called
11Spring Context initialized
12Bean retrieved from Spring Context
13Employee Name=Pankaj
14Apr 01, 2014 10:50:50 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
15INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@c1b9b03: startup date [Tue Apr 01 22:50:50 PDT 2014]; root of context hierarchy
16MyService destroy method called
17MyEmployeeService Closing resources
18EmployeeService Closing resources
19Spring Context Closed
春豆生命周期的关键点**:
- 从控制台输出,很明显 Spring Context 首先使用 no-args 构造器来初始化豆类对象,然后调用 post-init 方法
- 豆类初始化的顺序与春豆配置文件中定义的顺序相同
- 背景只有在所有春豆都经过 post-init 方法执行程序的正确初始化时才返回
- 员工名称被打印为
Pankaj
,因为它在后起始方法中被初始化 - 当背景被关闭时,豆类就会被摧毁,以其初始化为 LIFO(Last-In-First-Out)顺序
您可以删除代码以获取类型的MyEmployeeService
,并确认输出将是相似的,并遵循上述所有点。
春天知觉界面
有时我们需要在豆子中使用 Spring Framework 对象来进行一些操作,例如读取 ServletConfig 和 ServletContext 参数,或者了解应用程序Context 所加载的豆类定义. 这就是为什么春季框架提供了一组*智能界面,我们可以在豆类中执行. `org.springframework.beans.factory.Award'是所有这些有意识界面的根标记界面。 *Aware接口都是"知觉"的分界面,并声明由豆子执行的单一设置方法. 然后春上下文使用基于定子的依赖性注射,将相应的物体注入到豆中并提供给我们使用. 春知界面类似于 [servlet listers] (/community/touristics/ servletcontextlistener-servlet-servlet-listener-example) (/社区/touris/ servletcontextlistenter-servlet-listenter-example) 互联网档案馆的存檔,存档日期2014-12-11. "Servlet Listers Eventioners – Servlet Context Listener, HttpSession Listener and Servlet Lesser"),具有回调方法和执行观察家设计模式. (原始内容存档于2018-10-21). " Observative Design Pattern in Java – Electory". 一些重要的知觉界面包括:
- ApplicationContextAware - 注入ApplicationContext对象,示例使用是获取定义名称的数组
- BeanFactoryAware - 注入BeanFactory对象,示例使用是检查的范围
- BeanNameAware - 知道在配置文件中定义的名
- ResourceLoaderAware - 注入ResourceLoader对象,示例使用是获取类路径中的文件的输入流 *Serv CletContextAware - 在应用程序中注入ServletContext对象MVC,示例使用是读取背景参数和属性(_M
让我们通过在我们将配置为春豆的类中实施少数这些知情界面在行动中的使用来看看。
1package com.journaldev.spring.service;
2
3import java.util.Arrays;
4
5import org.springframework.beans.BeansException;
6import org.springframework.beans.factory.BeanClassLoaderAware;
7import org.springframework.beans.factory.BeanFactory;
8import org.springframework.beans.factory.BeanFactoryAware;
9import org.springframework.beans.factory.BeanNameAware;
10import org.springframework.context.ApplicationContext;
11import org.springframework.context.ApplicationContextAware;
12import org.springframework.context.ApplicationEventPublisher;
13import org.springframework.context.ApplicationEventPublisherAware;
14import org.springframework.context.EnvironmentAware;
15import org.springframework.context.ResourceLoaderAware;
16import org.springframework.context.annotation.ImportAware;
17import org.springframework.core.env.Environment;
18import org.springframework.core.io.Resource;
19import org.springframework.core.io.ResourceLoader;
20import org.springframework.core.type.AnnotationMetadata;
21
22public class MyAwareService implements ApplicationContextAware,
23 ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,
24 BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware {
25
26 @Override
27 public void setApplicationContext(ApplicationContext ctx)
28 throws BeansException {
29 System.out.println("setApplicationContext called");
30 System.out.println("setApplicationContext:: Bean Definition Names="
31 + Arrays.toString(ctx.getBeanDefinitionNames()));
32 }
33
34 @Override
35 public void setBeanName(String beanName) {
36 System.out.println("setBeanName called");
37 System.out.println("setBeanName:: Bean Name defined in context="
38 + beanName);
39 }
40
41 @Override
42 public void setBeanClassLoader(ClassLoader classLoader) {
43 System.out.println("setBeanClassLoader called");
44 System.out.println("setBeanClassLoader:: ClassLoader Name="
45 + classLoader.getClass().getName());
46 }
47
48 @Override
49 public void setResourceLoader(ResourceLoader resourceLoader) {
50 System.out.println("setResourceLoader called");
51 Resource resource = resourceLoader.getResource("classpath:spring.xml");
52 System.out.println("setResourceLoader:: Resource File Name="
53 + resource.getFilename());
54 }
55
56 @Override
57 public void setImportMetadata(AnnotationMetadata annotationMetadata) {
58 System.out.println("setImportMetadata called");
59 }
60
61 @Override
62 public void setEnvironment(Environment env) {
63 System.out.println("setEnvironment called");
64 }
65
66 @Override
67 public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
68 System.out.println("setBeanFactory called");
69 System.out.println("setBeanFactory:: employee bean singleton="
70 + beanFactory.isSingleton("employee"));
71 }
72
73 @Override
74 public void setApplicationEventPublisher(
75 ApplicationEventPublisher applicationEventPublisher) {
76 System.out.println("setApplicationEventPublisher called");
77 }
78
79}
Spring *Aware 配置文件示例
非常简单的春豆配置文件。
1<?xml version="1.0" encoding="UTF-8"?>
2<beans xmlns="https://www.springframework.org/schema/beans"
3 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
5
6<bean name="employee" class="com.journaldev.spring.bean.Employee" />
7
8<bean name="myAwareService" class="com.journaldev.spring.service.MyAwareService" />
9
10</beans>
春季:Aware测试计划
1package com.journaldev.spring.main;
2
3import org.springframework.context.support.ClassPathXmlApplicationContext;
4
5import com.journaldev.spring.service.MyAwareService;
6
7public class SpringAwareMain {
8
9 public static void main(String[] args) {
10 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-aware.xml");
11
12 ctx.getBean("myAwareService", MyAwareService.class);
13
14 ctx.close();
15 }
16
17}
现在,当我们在类上执行时,我们会跟踪输出。
1Apr 01, 2014 11:27:05 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
2INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@60a2f435: startup date [Tue Apr 01 23:27:05 PDT 2014]; root of context hierarchy
3Apr 01, 2014 11:27:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
4INFO: Loading XML bean definitions from class path resource [spring-aware.xml]
5setBeanName called
6setBeanName:: Bean Name defined in context=myAwareService
7setBeanClassLoader called
8setBeanClassLoader:: ClassLoader Name=sun.misc.Launcher$AppClassLoader
9setBeanFactory called
10setBeanFactory:: employee bean singleton=true
11setEnvironment called
12setResourceLoader called
13setResourceLoader:: Resource File Name=spring.xml
14setApplicationEventPublisher called
15setApplicationContext called
16setApplicationContext:: Bean Definition Names=[employee, myAwareService]
17Apr 01, 2014 11:27:05 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
18INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@60a2f435: startup date [Tue Apr 01 23:27:05 PDT 2014]; root of context hierarchy
测试程序的控制台输出易于理解,我不会深入了解这方面的细节。这就是春豆生命周期方法和注入框架的特定对象。请从下面的链接下载样本项目并分析它来了解更多。