Spring基础知识(4)- Spring Bean (一) | 简介、定义

 

在 Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 Bean。Bean 是一个由 Spring IoC 容器实例化、装配和管理的对象。

简而言之:
    (1) Bean 是对象,一个或者多个不限定;
    (2) Bean 由 Spring IoC 容器管理;
    (3) Bean 是 Spring 应用程序的主要组成部分(或称为主要的功能模块);

IoC 容器通过获取 Java 类和该类相关的 Spring 配置元数据来进行实例化、装配和管理 Bean。

Spring 配置元数据一般包含如下信息:

    (1) 如何创建一个 Bean;
    (2) Bean 的作用域、生命周期等信息;
    (3) Bean 的依赖关系、如何装配等信息;

Spring 的三种 Bean 配置方式:

    (1) 基于配置文件 (XML格式、Properties格式) 的配置方式;
    (2) 基于注解的配置方式;
    (3) 基于Java配置(@Configuration)的配置方式;

    即 Spring 配置元数据,可以在配置文件里,或在注解中。


1. 基于配置文件 (XML格式和Properties格式) 的配置方式

    (1) Beans 配置文件 (主配置文件)

 1         <?xml version="1.0" encoding="UTF-8"?>
 2         <beans xmlns="http://www.springframework.org/schema/beans"
 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             <bean id="man" class="com.example.Man">
11                 <!-- 构造函数注入 -->
12                 <constructor-arg value="Spring constructor method" />
13 
14                 <!-- setter 注入 -->
15                 <property name="age" value="25"></property>
16                 <property name="dependValue" value="Man set dependValue"></property>
17 
18             </bean>
19             <bean id="person" class="com.example.Person">
20                 <!-- 构造函数注入 -->
21                 <constructor-arg ref="man" type="com.example.Man"/>
22 
23                 <!-- 级联属性 setter 注入 -->
24                 <property name="man.dependValue" value="Person set man.dependValue"></property>
25                 
26                 <!-- setter 注入 Null, Empty 值 -->
27                 <property name="nullValue"><null/></property>
28                 <property name="emptyValue" value=""></property> 
29 
30                 <!--使用 <![CDATA[]]> setter 注入特殊符号 -->
31                 <property name="literalString">
32                     <value><![CDATA[<www.test.com>]]></value>
33                 </property>
34 
35                 <!-- setter 注入集合<array>, <list>, <map>, <set> -->
36                 <property name="array">
37                     <array>
38                         <value>Array 1</value>
39                         <value>Array 2</value>
40                         <value>Array 3</value>
41                     </array>
42                 </property>
43                 <property name="list">
44                     <list>
45                         <value>List 1</value>
46                         <value>List 2</value>
47                         <value>List 3</value>
48                     </list>
49                 </property>
50                 <property name="map">
51                     <map>
52                         <entry key="1" value="Map 1"></entry>
53                         <entry key="2" value="Map 2"></entry>
54                     </map>
55                 </property>
56                 <property name="set">
57                     <set>
58                         <value>Set 1</value>
59                         <value>Set 2</value>
60                         <value>Set 3</value>
61                     </set>
62                 </property>
63 
64             </bean>
65 
66         </beans>

 

        上面的 <bean>标签就是用于配置 Bean 对象让 Spring 来创建的,<constructor-arg>标签就是告诉  Spring 使用构造函数注入,<property>标签就是告诉 Spring 使用 setter 注入。

        Spring 可以通过 2 种方式实现属性注入:构造函数注入和 setter 注入(又称设值注入)。

        *注:这里 Beans 配置文件保存为 spring-beans.xml,具体使用方式,参考 “Spring基础知识(2)- 创建 Spring 程序”,下同。
        
    (2) 示例

  1         package com.example;
  2 
  3         import java.util.List;
  4         import java.util.Map;
  5         import java.util.Set;
  6         import java.util.Arrays;
  7 
  8         import org.springframework.context.support.ClassPathXmlApplicationContext;
  9         import org.springframework.context.ApplicationContext;
 10 
 11         public class App {
 12             public static void main( String[] args ) {
 13                 ApplicationContext context1 = new ClassPathXmlApplicationContext("spring-beans.xml");
 14                 Person person = (Person) context1.getBean("person");
 15                 person.display();
 16             }
 17         }
 18 
 19         class Man {
 20             String name;
 21             int age;
 22             private String dependValue;
 23 
 24             // 有其它有参构造函数,所以不要省略
 25             public Man() {
 26 
 27             }
 28 
 29             public Man(String name) {
 30                 this.name = name;
 31             }
 32 
 33             public void setDependValue(String dependValue) {
 34                 this.dependValue = dependValue;
 35             }
 36 
 37             public void display() {
 38                 System.out.println("Man -> display(): name = " + name
 39                                                     + ", age = " + age
 40                                                     + ", dependValue = " + dependValue);
 41             }
 42 
 43             public void setAge(int age) {
 44                 this.age = age;
 45             }
 46         }
 47 
 48         class Person {
 49             private Man man;
 50             private String nullValue;
 51             private String emptyValue;
 52             private String literalString;
 53             private String[] array;
 54             private List<String> list;
 55             private Map<String, String> map;
 56             private Set<String> set;
 57 
 58             // 有其它有参构造函数,所以不要省略
 59             public Person() {
 60 
 61             }
 62 
 63             public Person(Man man) {
 64                 this.man = man;
 65             }
 66 
 67             // 使用级联属性 setter 注入,需提供一个依赖对象的 getXxx() 方法
 68             public Man getMan() {
 69                 return man;
 70             }
 71 
 72             public void display() {
 73                 man.display();
 74                 System.out.println("Person -> display(): nullValue = " + nullValue
 75                                                     + ", emptyValue = " + emptyValue
 76                                                     + ", literalString = " + literalString);
 77                 System.out.println("Person -> display(): array = " +  Arrays.toString(array));
 78                 System.out.println("Person -> display(): list = " + list);
 79                 System.out.println("Person -> display(): map = " + map);
 80                 System.out.println("Person -> display(): set = " + set);
 81             }
 82 
 83             public void setNullValue(String nullValue) {
 84                 this.nullValue = nullValue;
 85             }
 86 
 87             public void setEmptyValue(String emptyValue) {
 88                 this.emptyValue = emptyValue;
 89             }
 90 
 91             public void setLiteralString(String literalString) {
 92                 this.literalString = literalString;
 93             }
 94 
 95             public void setArray(String[] array) {
 96                 this.array = array;
 97             }
 98 
 99             public void setList(List<String> list) {
100                 this.list = list;
101             }
102 
103             public void setMap(Map<String, String> map) {
104                 this.map = map;
105             }
106 
107             public void setSet(Set<String> set) {
108                 this.set = set;
109             }
110         }

 

2. 基于注解的配置方式

    (1) Beans 配置文件 (主配置文件)
    
        Spring 默认不使用注解装配 Bean,因此我们需要在 Spring 的 XML 配置中,通过 <context:component-scan> 元素开启 Spring Beans的自动扫描功能。

 1         <?xml version="1.0" encoding="UTF-8"?>
 2         <beans xmlns="http://www.springframework.org/schema/beans"
 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             <context:component-scan base-package="com.example" />
11 
12         </beans>

        添加 <context:component-scan> 标签,spring 就会去自动扫描 com.example 包内的 java 文件,如果扫描到文件中带有@Service, @Component, @Repository ,@Controller 等这些注解的类,则把这些类注册为 bean。

    (2) 示例

 1         package com.example;
 2 
 3         import java.util.List;
 4         import java.util.Map;
 5         import java.util.Set;
 6         import java.util.Arrays;
 7 
 8         import javax.annotation.Resource;
 9         import org.springframework.stereotype.Component;
10         import org.springframework.beans.factory.annotation.Value;
11 
12         import org.springframework.context.support.ClassPathXmlApplicationContext;
13         import org.springframework.context.ApplicationContext;
14 
15         public class App {
16             public static void main( String[] args ) {
17                 ApplicationContext context1 = new ClassPathXmlApplicationContext("spring-beans.xml");
18                 Person2 person2 = (Person2) context1.getBean("person2");
19                 person2.display();
20             }
21         }
22 
23         @Component("man2")
24         class Man2 {
25             @Value("Spring setter method")
26             String name;
27 
28             // 有其它有参构造函数,所以不要省略
29             public Man2() {
30 
31             }
32 
33             public Man2(String name) {
34                 this.name = name;
35             }
36 
37             public void display() {
38                 System.out.println("Man2 -> display(): name = " + name);
39             }
40         }
41 
42         @Component("person2")
43         class Person2 {
44             @Resource(name="man2")
45             private Man2 man2;
46 
47             private String nullValue;
48             @Value("")
49             private String emptyValue;
50             @Value("<www.spring.com>")
51             private String literalString;
52 
53             @Value("#{'1,2,3'.split(',')}")  // #{} 是 SpEL 表达式语言
54             private String[] array;
55             @Value("#{'\"Java\",\"Spring\",\"Idea\"'.split(',')}")
56             private List<String> list;
57             @Value("#{'\"Tree\",\"Dog\",\"River\"'.split(',')}")
58             private Set<String> set;
59             @Value("#{{\"name\":\"Tester\",\"age\": 21}}")
60             private Map<String, String> map;
61 
62             // 有其它有参构造函数,所以不要省略
63             public Person2() {
64 
65             }
66 
67             public Person2(Man2 man2) {
68                 this.man2 = man2;
69             }
70 
71             public void display() {
72                 man2.display();
73                 System.out.println("Person2 -> display(): nullValue = " + nullValue
74                                                 + ", emptyValue = " + emptyValue
75                                                 + ", literalString = " + literalString);
76                 System.out.println("Person2 -> display(): array = " +  Arrays.toString(array));
77                 System.out.println("Person2 -> display(): list = " + list);
78                 System.out.println("Person2 -> display(): set = " + set);
79                 System.out.println("Person2 -> display(): map = " + map);
80             }
81         }

 

3. 基于Java配置(@Configuration)的配置方式

    1) @Bean注解

        Spring @Bean 是一个方法级别的注解,用于产生一个被 Spring IoC 容器所管理的 Bean。通常情况下,@Bean 可以与 @Configuration 和 @Component 注解一起使用。

        在默认情况下 @Bean 注解所产生的 Bean 是单例模式的,此外,@Bean 还可以与 @Scope, @Lazy, @DependOn 和@Primary 注解一起使用。

属性 描述
name 用于指定Bean的名称
value name 的别名,效果等同于 name
initMethod 在初始化Bean实例时需要调用的方法名称。默认没有要调用的方法
destroyMethod 在关闭应用上下文时要在Bean中调用的方法名称,默认不调用任何方法
autowireCandidate 布尔类型,用于限定当前的Bean是否可以自动注入到其他Bean中,默认是true


        *注: initMethod、destroyMethod 指定的方法必须是不带参数的方法,且该方法允许在运行时抛出异常

    2)  @Configuration 和 @Bean 搭配使用

        Spring 3.0 开始提供 @Configuration 注解用于定义配置类,可代替 XML 配置文件,被注解的类内部包含有一个或多个被 @Bean 注解的方法。

        这些方法将会被 AnnotationConfigApplicationContext 或 AnnotationConfigWebApplicationContext 类进行扫描,并用于构建 bean 定义,初始化 Spring 容器。

        示例:

 1     package com.example;
 2 
 3     import org.springframework.beans.factory.annotation.Value;
 4     import org.springframework.context.annotation.Bean;
 5     import org.springframework.context.annotation.Configuration;
 6     import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 7 
 8     public class App {
 9         public static void main( String[] args ) {
10 
11             AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ManualBeanConfig.class);
12             Forest forest = context.getBean(Forest.class);
13             forest.display();
14             context.close();
15 
16         }
17     }
18 
19     class Tree {
20         @Value("Tree name")
21         private String name;
22 
23         public void setName(String name) {
24             this.name = name;
25         }
26 
27         public void display() {
28             System.out.println("Tree -> display(): name = " + name);
29         }
30     }
31 
32     class Forest {
33         @Value("Forest name")
34         private String name;
35         private Tree tree;
36 
37         public void setTree(Tree tree) {
38             this.tree = tree;
39         }
40 
41         public void setName(String name) {
42             this.name = name;
43         }
44 
45         public void display() {
46             tree.display();
47             System.out.println("Forest -> display(): name = " + name);
48         }
49 
50         public void init() {
51             System.out.println("Forest -> init()");
52         }
53 
54         public void destroy() {
55             System.out.println("Forest -> destroy()");
56         }
57     }
58 
59     @Configuration
60     class ManualBeanConfig {
61 
62         public ManualBeanConfig() {
63             System.out.println("ManualBeanConfig -> ManualBeanConfig()");
64         }
65 
66         @Bean
67         public Tree getTree() {
68             return new Tree();
69         }
70 
71         @Bean(initMethod = "init", destroyMethod = "destroy" )
72         public Forest getForest() {
73             Forest forest = new Forest();
74             forest.setTree(getTree());
75             return forest;
76         }
77     }

 

        输出:

            ManualBeanConfig -> ManualBeanConfig()
            Forest -> init()
            Tree -> display(): name = Tree name
            Forest -> display(): name = Forest name
            Forest -> destroy()

posted @ 2022-03-06 18:28  垄山小站  阅读(333)  评论(0)    收藏  举报