Spring基础知识(6)- Spring Bean (三)


Spring后置处理器、Spring Bean继承


1. Spring后置处理器

    BeanPostProcessor 接口也被称为后置处理器,通过该接口可以自定义调用初始化前后执行的操作方法。

    该接口中包含了两个方法:

        postProcessBeforeInitialization() 方法:在 Bean 实例化、属性注入后,初始化前调用。  
        postProcessAfterInitialization() 方法:在 Bean 实例化、属性注入、初始化都完成后调用。

    添加多个后置处理器实现类时,默认情况下 Spring 容器会根据后置处理器的定义顺序来依次调用。也可以通过实现 Ordered 接口的 getOrder() 方法指定后置处理器的执行顺序。该方法返回值为整数,默认值为 0,取值越大优先级越低。

    Spring 配置文件(spring-beans.xml),配置格式如下:

 1         <?xml version="1.0" encoding="UTF-8"?>
 2          3             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4             xmlns:context="http://www.springframework.org/schema/context"
 5             xsi:schemaLocation="http://www.springframework.org/schema/beans
 6                                 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 7                                 http://www.springframework.org/schema/context
 8                                 http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 9 
10             class="com.example.Task" init-method="init" destroy-method="destroy">
11                 
12             
13             class="com.example.BeforeTask" />
14             class="com.example.BeforeTask2" />
15 
16         


    示例:

 1         package com.example;
 2 
 3         import org.springframework.beans.BeansException;
 4         import org.springframework.beans.factory.config.BeanPostProcessor;
 5         import org.springframework.core.Ordered;
 6         import org.springframework.context.support.ClassPathXmlApplicationContext;
 7 
 8         public class App {
 9             public static void main( String[] args ) {
10 
11                 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");
12                 Task task = (Task) context.getBean("task");
13                 task.display();
14                 context.close();
15 
16             }
17         }
18 
19         class Task {
20             private String name;
21 
22             public void setName(String name) {
23                 this.name = name;
24             }
25 
26             public void display() {
27                 System.out.println("Task -> display(): name = " + name);
28             }
29 
30             public void init() {
31                 System.out.println("Task -> init()");
32             }
33 
34             public void destroy() {
35                 System.out.println("Task -> destroy()");
36             }
37         }
38 
39         class BeforeTask implements BeanPostProcessor, Ordered {
40             @Override
41             public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
42                 System.out.println("BeforeTask -> postProcessBeforeInitialization(): beanName = " + beanName);
43                 return bean;
44             }
45             @Override
46             public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
47                 System.out.println("BeforeTask -> postProcessAfterInitialization(): beanName = " + beanName);
48                 return bean;
49             }
50             @Override
51             public int getOrder() {
52                 return 0;
53             }
54         }
55 
56         class BeforeTask2 implements BeanPostProcessor, Ordered {
57             @Override
58             public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
59                 System.out.println("BeforeTask2 -> postProcessBeforeInitialization(): beanName = " + beanName);
60                 return bean;
61             }
62             @Override
63             public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
64                 System.out.println("BeforeTask2 -> postProcessAfterInitialization(): beanName = " + beanName);
65                 return bean;
66             }
67             @Override
68             public int getOrder() {
69                 return 2;
70             }
71         }


    输出:

        BeforeTask -> postProcessBeforeInitialization(): beanName = task
        BeforeTask2 -> postProcessBeforeInitialization(): beanName = task
        Task -> init()
        BeforeTask -> postProcessAfterInitialization(): beanName = task
        BeforeTask2 -> postProcessAfterInitialization(): beanName = task
        Task -> display(): name = Bean post processor
        Task -> destroy()


2. Spring Bean继承

    Spring 中,Bean 和 Bean 之间也存在继承关系,这种继承与 Java 类的继承无关,但是继承的概念是一样的。我们将被继承的 Bean 称为父 Bean,将继承父 Bean 配置信息的 Bean 称为子 Bean。

    Spring Bean 的定义中可以包含很多配置信息,例如构造方法参数、属性值。子 Bean 既可以继承父 Bean 的配置数据,也可以根据需要重写或添加属于自己的配置信息。

    1) 一般继承

        Spring 配置文件(spring-beans.xml)设置继承关系,配置格式如下:

 1             <?xml version="1.0" encoding="UTF-8"?>
 2              3                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4                 xmlns:context="http://www.springframework.org/schema/context"
 5                 xsi:schemaLocation="http://www.springframework.org/schema/beans
 6                                     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 7                                     http://www.springframework.org/schema/context
 8                                     http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 9 
10                 class="com.example.ParentBean">
11                     
12                     
13                 
14                 class="com.example.ChildBean" parent="parentBean">
15                     
16                 
17             


        示例:

 1            package com.example;
 2 
 3             import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 
 5             public class ExtendsApp {
 6                 public static void main( String[] args ) {
 7 
 8                     ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");
 9                     ChildBean childBean = (ChildBean) context.getBean("childBean");
10                     childBean.display();
11 
12                 }
13             }
14 
15             class ParentBean {
16                 private String name;
17                 private int age;
18 
19                 public void setName(String name) {
20                     System.out.println("ParentBean -> setName('" + name + "')");
21                     this.name = name;
22                 }
23 
24                 public void setAge(int age) {
25                     System.out.println("ParentBean -> setAge('" + age + "')");
26                     this.age = age;
27                 }
28 
29                 public void display() {
30                     System.out.println("ParentBean -> display(): name = " + name + ", age = " + age);
31                 }
32             }
33 
34             class ChildBean {
35                 private String name;
36                 private int age;
37 
38 
39                 public void setName(String name) {
40                     System.out.println("ChildBean -> setName('" + name + "')");
41                     this.name = name;
42                 }
43 
44                 public void setAge(int age) {
45                     System.out.println("ChildBean -> setAge('" + age + "')");
46                     this.age = age;
47                 }
48 
49                 public void display() {
50                     System.out.println("ChildBean -> display(): name = " + name + ", age = " + age);
51                 }
52             }


        输出:

            ParentBean -> setName('Parent Test')
            ParentBean -> setAge('1')
            ChildBean -> setName('Child Test')
            ChildBean -> setAge('1')
            ChildBean -> display(): name = Child Test, age = 1

    2) 模板继承

        在父 Bean 的定义中,可以不指定 class 属性,这个父 Bean 的 abstract 属性为 true,父类只是个模板。
        
        Spring 配置文件(spring-beans.xml)设置继承关系,配置格式如下:

 1             <?xml version="1.0" encoding="UTF-8"?>
 2              3                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4                 xmlns:context="http://www.springframework.org/schema/context"
 5                 xsi:schemaLocation="http://www.springframework.org/schema/beans
 6                                     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 7                                     http://www.springframework.org/schema/context
 8                                     http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 9 
10                 abstract="true">
11                     
12                     
13                 
14                 class="com.example.ChildBean" parent="parentBean">
15                     
16                 
17             

       
        示例:

            与 “ 1) 一般继承” 的代码一样。

        输出:

            ChildBean -> setName('Child Test (abstract)')
            ChildBean -> setAge('2')
            ChildBean -> display(): name = Child Test (abstract), age = 2