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 <bean 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 <bean 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 <beans xmlns="http://www.springframework.org/schema/beans"
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     <bean id="master" class="com.lx.test8.Master">
34         <property name="name" value="小明"/>
35         <!-- <property name="dog" ref="a"/> -->
36     </bean>
37 
38     <bean id="myDog" class="com.lx.test8.Dog">
39         <property name="name" value="大黄"/>
40         <property name="age" value="3"/>
41     </bean>
42 
43 </beans>
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方式注入

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

  1 public class Department {
  2     private String name;
  3     private String[] strArray; // 数组
  4     private List<Employee> empList; // list集合
  5     private Set<Employee> empSet; // set集合
  6     private Map<String, Employee> empMap; // map集合
  7     private Properties properties; // Properties的使用
  8     private List<String> 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 <bean id="emp1" class="com.lx.spring.day1.Employee">
 22     <property name="name" value="张三"/>
 23     <property name="id" value="20200001"/>
 24 </bean>
 25 
 26 <bean id="emp2" class="com.lx.spring.day1.Employee">
 27     <property name="name" value="李四"/>
 28     <property name="id" value="20200002"/>
 29 </bean>
 30 
 31 <bean id="department" class="com.lx.spring.day1.Department">
 32     <property name="name" value="财务部"/>
 33     <!--  <property name="name"><null/></property>  注入null-->
 34 
 35     <!-- 给数组注入值 -->
 36     <property name="strArray">
 37         <list>
 38             <value>strArray1</value>
 39             <value>strArray2</value>
 40             <value>strArray3</value>
 41         </list>
 42     </property>
 43     <!-- 给list注入值.有序 -->
 44     <property name="empList">
 45         <list>
 46             <ref bean="emp2"/>
 47             <ref bean="emp1"/>
 48             <ref bean="emp1"/>
 49             <bean class="com.lx.spring.day1.Employee">
 50                 <property name="name" value="配置的bean"/>
 51                 <property name="id" value="2020"/>
 52             </bean>
 53         </list>
 54     </property>
 55     <!-- 给set注入值.无序.不重复 -->
 56     <property name="empSet">
 57         <set>
 58             <ref bean="emp1"/>
 59             <ref bean="emp2"/>
 60             <ref bean="emp2"/>
 61         </set>
 62     </property>
 63     <!-- 给map注入值. -->
 64     <property name="empMap">
 65         <map>
 66             <entry key="11" value-ref="emp1"/>
 67             <entry key="22" value-ref="emp2"/>
 68             <entry key="22" value-ref="emp1"/>
 69         </map>
 70     </property>
 71     <!-- 给属性集合配置 -->
 72     <property name="properties">
 73         <props>
 74             <prop key="pp1">abcd</prop>
 75             <prop key="pp2">hello</prop>
 76         </props>
 77     </property>
 78 </bean>
 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<String, Employee> empMap = department.getEmpMap();
103         Iterator<String> 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<String, Employee> 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<Object, Object> entry : properties.entrySet()) {
119             System.out.println("key=" + entry.getKey() + " " + entry.getValue());
120         }
121 
122         System.out.println("-------取出properties-Enumeration-------");
123         Enumeration<Object> 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 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        
 5        <!--1.引入名称空间 util-->
 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     <!--2.提取公共片段-->
14     <util:list id="partListStr">
15         <value>易筋经</value>
16         <value>九阴真经</value>
17         <value>九阳神功</value>
18     </util:list>
19 
20     <!--3.注入-->
21     <bean id="depart" class="com.lx.spring.day1.Department">
22         <property name="listStr" ref="partListStr"/>
23     </bean>
24 
25 </beans>

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 <bean id="person" class="com.lx.test6.Person">
15     <property name="name" value="人"/>
16     <property name="age" value="21"/>
17 </bean>
18 
19 <bean id="student" parent="person" class="com.lx.test6.Student">
20     <!-- 会覆盖从父类继承的属性 -->
21     <property name="name" value="小明"/>
22     <property name="degree" value="学士"/>
23 </bean>
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 <bean id="student" class="com.lx.test6.Student">
14     <!-- 通过构造函数来注入属性值 -->
15     <constructor-arg index="0" type="java.lang.String" value="学生"/>
16     <constructor-arg index="1" type="int" value="22"/>
17 </bean>
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 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        
 5        <!-- 1.添加p名称空间 -->
 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     <!-- 2.通过p名称空间方式注入属性值 -->
11     <bean id="t" class="com.lx.spring.day2.Teacher" p:name="张无忌" p:age="40"/>
12 
13 </beans>

5、FactoryBean(工厂bean)

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

 1 public class MyBean implements FactoryBean<Teacher> {
 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 <bean id="myBean" 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 <context:property-placeholder location="classpath:db1.properties,classpath:db2.properties"/>
10 
11 // 方式二
12 <bean id="configurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
13     <property name="locations">
14         <list>
15             <value>classpath:db1.properties</value>
16             <value>classpath:db2.properties</value>
17         </list>
18     </property>
19 </bean>
20 
21 <!-- $ 占位符获取属性变量的值 -->
22 <bean id="dBUtil1" class="com.lx.test8.DBUtil">
23     <property name="name" value="${name}"/>
24     <property name="drivername" value="${drivername}"/>
25     <property name="url" value="${url}"/>
26     <property name="pwd" value="${pwd}"/>
27 </bean>
posted @ 2020-09-05 17:58  Craftsman-L  阅读(163)  评论(0编辑  收藏  举报