• 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>

    作者:Craftsman-L

    本博客所有文章仅用于学习、研究和交流目的,版权归作者所有,欢迎非商业性质转载。

    如果本篇博客给您带来帮助,请作者喝杯咖啡吧!点击下面打赏,您的支持是我最大的动力!

  • 相关阅读:
    活用 %取余 用于变量循环
    jquery滚动条固定在某一位置
    jquary中各种相似操作介绍
    jquary中滚动条滚动到底部
    JSON到字符串之间的解析
    ecshop删去版权等信息
    分享代码和网页地图
    ecshop版权的修改,头部,底部
    ECSHOP中transport.js和jquery的冲突的简单解决办法
    从Eclipse迁移到Android Studio碰到的问题记录
  • 原文地址:https://www.cnblogs.com/originator/p/13619024.html
Copyright © 2020-2023  润新知