Spring5(三)——DI


一、装配Bean

1、介绍

  在spring容器内拼凑bean叫做装配。装配bean的时候,需要告诉容器有哪些bean以及容器如何使用依赖注入将它们配合在一起。
  使用XML装配,XML是最常见的spring应用系统配置源。几种spring容器都支持使用XML装配bean,包括:
  XmlBeanFactory:调用ClassPathResource载入上下文定义文件(比如applicationContext.xml)。
  ClassPathXmlApplicationContext:从类路径载入上下文定义文件。
  XmlWebApplicationContext:从web应用上下文中载入定义文件。

2、实例化与销毁

  spring实例化bean或销毁bean时,有时需要作一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法。
  // 非注解的方式

1 class="Foo" init-method="function-name" destory-method="function-name">

  // 注解的方式

1 @PostConstruct public void init(){…}
2 @PreDestroy public void destroy(){…}

  注意:注解的方式,bean只能扫描注入,不能与配置的方式混合用。且注解时步骤7、8顺序(bean的生命周期中的步骤)似乎有差别。

1 class="...CommonAnnotationBeanPostProcessor">

  spring也提供了两个接口来实现相同的功能:InitializingBean和DisposableBean,不推荐使用该接口,它将你的bean和springAPI邦定在一起,他们是一对。定制化是一对。

3、自动装配

  Spring Ioc容器可以自动装配(autowire)相互协作bean之间的关联关系。因此,可以自动让Spring通过检查BeanFactory中的内容来替我们指定bean的协作者。autowire的方便之处在减少或者消除属性或构造器参数的设置。

模式 描述
no 不自动装配
byName 根据属性名自动装配。检查容器并根据名字查找与属性名完全一致的bean,将其与属性自动装配。
byType 根据类型自动装配。检查容器中存在一个与指定属性类型相同的bean,将其与属性自动装配。
constructor 应用于构造参数。查找和bean的构造参数一致的一个或多个bean,若找不到或找到多个,抛异常。按照参数的类型装配。
autodetect 自动检测装配。先constructor后byType。
default 这个需要在   当在指定了default-atuowrite后,所有的bean的默认的autowire就是指定的装配方法。不写,则默认是defualt-autorwire=“no”

  bean的autowire不写,即autowire="default",表明模式跟随default-atuowrite
  bean的autowire指定,此时以bean的autowire为准。

  若default-atuowrite不写,即default-atuowrite="no",表明不自动装配。
  若default-atuowrite指定,所有的bean的默认的autowire就是指定的装配方法。

 1 public class Master {
 2     private String name;
 3     private Dog myDog;
 4 
 5     public Master() {
 6         System.out.println("====Master()====");
 7     }
 8 
 9     public Master(Dog dog) {
10         System.out.println("====Master(Dog dog)====");
11         this.myDog = dog;
12     }
13 
14    // getter && setter
15 }
16 
17 public class Dog {
18    private String name;
19    private int age;
20 
21    // getter && setter
22 }
23 
24 application.xml
25 <?xml version="1.0" encoding="UTF-8" ?>
26 27        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
28        xsi:schemaLocation="http://www.springframework.org/schema/beans
29        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"
30        default-autowire="byName"
31 >
32 
33     class="com.lx.test8.Master">
34         
35         
36     
37 
38     class="com.lx.test8.Dog">
39         
40         
41     
42 
43 
44 
45 public class Test {
46     public static void main(String[] args) {
47         ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
48         Master master = app.getBean(Master.class);
49         System.out.println(JSON.toJSONString(master));
50     }
51 }
52 
53 // ====Master()====
54 // {"myDog":{"age":3,"name":"大黄"},"name":"小明"}

  这里是按名字(id = 属性名)装配。其他情况修改测试一下即可。

二、DI

1、set方式注入

  元素的子元素指明了使用它们的set方法来注入。

  1 public class Department {
  2     private String name;
  3     private String[] strArray; // 数组
  4     private List empList; // list集合
  5     private Set empSet; // set集合
  6     private Map empMap; // map集合
  7     private Properties properties; // Properties的使用
  8     private List listStr; // list集合
  9     
 10     // getter && setter
 11 }
 12 public class Employee {
 13     private String name;
 14     private int id;
 15 
 16     // getter && setter
 17 }
 18 
 19 application.xml
 20 
 21 class="com.lx.spring.day1.Employee">
 22     
 23     
 24 
 25 
 26 class="com.lx.spring.day1.Employee">
 27     
 28     
 29 
 30 
 31 class="com.lx.spring.day1.Department">
 32     
 33     
 34 
 35     
 36     
 37         
 38             strArray1
 39             strArray2
 40             strArray3
 41         
 42     
 43     
 44     
 45         
 46             
 47             
 48             
 49             class="com.lx.spring.day1.Employee">
 50                 
 51                 
 52             
 53         
 54     
 55     
 56     
 57         
 58             
 59             
 60             
 61         
 62     
 63     
 64     
 65         
 66             
 67             
 68             
 69         
 70     
 71     
 72     
 73         
 74             abcd
 75             hello
 76         
 77     
 78 
 79 
 80 public class Main {
 81     public static void main(String[] args) {
 82         ApplicationContext app = new ClassPathXmlApplicationContext("app1.xml");
 83         Department department = (Department) app.getBean("department");
 84         System.out.println(department.getName());
 85 
 86         System.out.println("-------取出strArray-------");
 87         for (String s : department.getStrArray()) {
 88             System.out.println(s);
 89         }
 90 
 91         System.out.println("-------取出empList-------");
 92         for (Employee e : department.getEmpList()) {
 93             System.out.println(e.toString());
 94         }
 95 
 96         System.out.println("-------取出empSet-------");
 97         for (Employee e : department.getEmpSet()) {
 98             System.out.println(e.toString());
 99         }
100 
101         System.out.println("-------取出empMap-迭代器-------");
102         Map empMap = department.getEmpMap();
103         Iterator iterator = empMap.keySet().iterator();
104 
105         while (iterator.hasNext()) {
106             String key = iterator.next();
107             Employee e = empMap.get(key);
108             System.out.println("key=" + key + "  " + e.toString());
109         }
110 
111         System.out.println("-------取出empMap-for-------");
112         for (Map.Entry entry : department.getEmpMap().entrySet()) {
113             System.out.println("key=" + entry.getKey() + "  " + entry.getValue().toString());
114         }
115 
116         System.out.println("-------取出properties-for-------");
117         Properties properties = department.getProperties();
118         for (Map.Entry entry : properties.entrySet()) {
119             System.out.println("key=" + entry.getKey() + " " + entry.getValue());
120         }
121 
122         System.out.println("-------取出properties-Enumeration-------");
123         Enumeration enumeration = properties.keys();
124         while (enumeration.hasMoreElements()) {
125             String key = (String) enumeration.nextElement();
126             System.out.println(key + " " + properties.getProperty(key));
127         }
128     }
129 }

  把集合注入部分提取出来

 1 <?xml version="1.0" encoding="UTF-8"?>
 2  3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        
 5        
 6        xmlns:util="http://www.springframework.org/schema/util"
 7        xsi:schemaLocation="http://www.springframework.org/schema/beans
 8        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 9 
10        http://www.springframework.org/schema/util
11        http://www.springframework.org/schema/util/spring-util-4.3.xsd">
12 
13     
14     
15         易筋经
16         九阴真经
17         九阳神功
18     
19 
20     
21     class="com.lx.spring.day1.Department">
22         
23     
24 
25 

2、继承方式注入

 1 // 父类
 2 public class Person {
 3     private String name;
 4     private int age;
 5     // getter && setter
 6 }
 7 
 8 public class Student extends Person {
 9     private String degree;
10    // getter && setter
11 }
12 
13 application.xml
14 class="com.lx.test6.Person">
15     
16     
17 
18 
19 class="com.lx.test6.Student">
20     
21     
22     
23 
24 
25 public class Test {
26     public static void main(String[] args) {
27         ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
28         Student student = app.getBean(Student.class);
29         System.out.println(JSON.toJSONString(student));
30     }
31 }
32 
33 // {"age":21,"degree":"学士","name":"小明"}

3、构造器方式注入

 1 public class Student {
 2     private String name;
 3     private int age;
 4 
 5     public Student(String name, int age) {
 6         this.name = name;
 7         this.age = age;
 8     }
 9    // getter && setter
10 }
11 
12 application.xml
13 class="com.lx.test6.Student">
14     
15     
16     
17 
18 
19 public class Test {
20     public static void main(String[] args) {
21         ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
22         Student student = app.getBean(Student.class);
23         System.out.println(JSON.toJSONString(student));
24     }
25 }
26 
27 // {"age":22,"name":"学生"}

  这种方式,set注入的缺点是无法清晰表达哪些属性是必须的,哪些是可选的,构造注入的优势是通过构造强制依赖关系,不能实例化不完全的或无法使用的bean。

4、p名称空间方式注入(了解)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2  3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        
 5        
 6        xmlns:p="http://www.springframework.org/schema/p"
 7        xsi:schemaLocation="http://www.springframework.org/schema/beans
 8        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
 9 
10     
11     class="com.lx.spring.day2.Teacher" p:name="张无忌" p:age="40"/>
12 
13 

5、FactoryBean(工厂bean)

  在配置文件定义bean类型可以和返回类型不一样。

 1 public class MyBean implements FactoryBean {
 2 
 3     // 定义返回bean
 4     @Override
 5     public Teacher getObject() throws Exception {
 6         Teacher teacher = new Teacher();
 7         teacher.setAge(666);
 8         teacher.setName("武天老师");
 9         return teacher;
10     }
11 
12     @Override
13     public Class<?> getObjectType() {
14         return null;
15     }
16 
17     @Override
18     public boolean isSingleton() {
19         return false;
20     }
21 }
1 class="com.lx.spring.day4.MyBean"/>
 1 // 测试类
 2 public class Main {
 3     public static void main(String[] args) {
 4         ApplicationContext context = new ClassPathXmlApplicationContext("app4.xml");
 5         Teacher teacher = (Teacher) context.getBean("myBean");
 6         System.out.println(JSON.toJSONString(teacher));
 7     }
 8 }
 9 
10 // 结果
11 {"age":666,"name":"武天老师"}

三、分散配置(引入属性文件)

  代码示例:引入属性文件的两种方式

 1 // db1.properties
 2 name=db1
 3 drivername=oracle
 4 url=jdbc:oracle:thin:@127.0.0.1:1521:
 5 pwd=123456
 6 
 7 // application.xml
 8 // 方式一
 9 
10 
11 // 方式二
12 class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
13     
14         
15             classpath:db1.properties
16             classpath:db2.properties
17         
18     
19 
20 
21 
22 class="com.lx.test8.DBUtil">
23     
24     
25     
26     
27