• 09 Spring的依赖注入


    1.依赖注入(Dependency Injection)

    (1)IOC的作用:
      降低程序间的耦合(依赖关系)
    (2)依赖关系的管理:
      以后都交给spring来维护
      在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明
    (3)依赖关系的维护:
      就称之为依赖注入。
    依赖注入:
      能注入的数据类型:基本类型和String、其他bean类型(在配置文件中或者注解配置过的bean)、复杂类型/集合类型。
    注入的方式:有三种
      第一种:使用构造函数提供
      第二种:使用set方法提供
      第三种:使用注解提供

    (4)应用案例搭建

    <1>业务层的接口:IAccountService.java

    package service;
    
    /**
     * 账户业务层的接口
     */
    public interface IAccountService {
    
        /**
         * 模拟保存账户
         */
        void saveAccount();
    }

    <2>业务层的接口实现类:AccountServiceImpl.java

    package service.impl;
    import service.IAccountService;
    
    import java.util.Date;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl implements IAccountService {
    
        //如果是经常变化的数据,并不适用于注入的方式
        private String name;
        private Integer age;
        private Date birthday;
    
        public AccountServiceImpl(String name,Integer age,Date birthday){
            this.name = name;
            this.age = age;
            this.birthday = birthday;
        }
    
        public AccountServiceImpl(){
            System.out.println("对象创建了");
        }
    
        public void  saveAccount(){
            System.out.println("AccountServiceImpl中的saveAccount方法执行了"+name+","+age+","+birthday);
        }
    
    }

    <3>表现层

    package ui;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import service.IAccountService;
    import service.impl.AccountServiceImpl;
    
    /**
     * 模拟一个表现层,用于调用业务层
     */
    public class Client {
    
        /**
         * 获取spring的Ioc核心容器,并根据id获取对象
         *
         * ApplicationContext的三个常用实现类:
         *      ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用)
         *      FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)
         *
         *      AnnotationConfigApplicationContext:它是用于读取注解创建容器的,是明天的内容。
         *
         * 核心容器的两个接口引发出的问题:
         *  ApplicationContext:     单例对象适用              采用此接口
         *      它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。
         *
         *  BeanFactory:            多例对象使用
         *      它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。
         * @param args
         */
        public static void main(String[] args) {
            //1.获取核心容器对象
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    
            //2.根据id获取Bean对象,注意id是在bean.xml文件配置的
            IAccountService as  = (IAccountService)ac.getBean("accountService");
            as.saveAccount();
    
    
        }
    }

    (5)依赖注入

    <1>使用构造函数注入(尽量不使用)

    使用的标签:constructor-arg
    标签出现的位置:bean标签的内部
    标签中的属性
      type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
      index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
      name:用于指定给构造函数中指定名称的参数赋值 常用的
    =============以上三个用于指定给构造函数中哪个参数赋值===============================
      value:用于提供基本类型和String类型的数据
      ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象

    优势:
      在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
    弊端:
      改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <!--构造函数注入:
            使用的标签:constructor-arg
            标签出现的位置:bean标签的内部
            标签中的属性
                type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
                index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
                name:用于指定给构造函数中指定名称的参数赋值                                        常用的
                =============以上三个用于指定给构造函数中哪个参数赋值===============================
                value:用于提供基本类型和String类型的数据
                ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
    
            优势:
                在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
            弊端:
                改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
        -->
        <bean id="accountService" class="service.impl.AccountServiceImpl" scope="prototype">
            <constructor-arg name="name" value="泰斯特"></constructor-arg>
            <constructor-arg name="age" value="18"></constructor-arg>
            <constructor-arg name="birthday" ref="now"></constructor-arg>
        </bean>
    
        <!-- 配置一个日期对象 -->
        <bean id="now" class="java.util.Date"></bean>
    
    </beans>

    <2>set方法注入(最常用的方式)

    涉及的标签:property
    出现的位置:bean标签的内部
    标签的属性
      name:用于指定注入时所调用的set方法名称
      value:用于提供基本类型和String类型的数据
      ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
    优势:
      创建对象时没有明确的限制,可以直接使用默认构造函数
    弊端:
      如果有某个成员必须有值,则获取对象是有可能set方法没有执行。

      (1)普通数据类型的注入:

    业务层的接口实现类:AccountServiceImpl2.java

    package service.impl;
    import service.IAccountService;
    
    import java.util.Date;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl2 implements IAccountService {
    
        //如果是经常变化的数据,并不适用于注入的方式
        private String name;
        private Integer age;
        private Date birthday;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public AccountServiceImpl2(){
            System.out.println("对象创建了");
        }
    
        public void  saveAccount(){
            System.out.println("AccountServiceImpl中的saveAccount方法执行了"+name+","+age+","+birthday);
        }
    
    }

    bean.xml配置如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <!-- 配置一个日期对象 -->
        <bean id="now" class="java.util.Date"></bean>
    
        <!-- set方法注入                更常用的方式
            涉及的标签:property
            出现的位置:bean标签的内部
            标签的属性
                name:用于指定注入时所调用的set方法名称
                value:用于提供基本类型和String类型的数据
                ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
            优势:
                创建对象时没有明确的限制,可以直接使用默认构造函数
            弊端:
                如果有某个成员必须有值,则获取对象是有可能set方法没有执行。
        -->
        <bean id="accountService2" class="service.impl.AccountServiceImpl2">
            <property name="name" value="TEST" ></property>
            <property name="age" value="21"></property>
            <property name="birthday" ref="now"></property>
        </bean>
    
    </beans>

    (2)复杂类型数据的注入:

    复杂类型的注入/集合类型的注入
      (1)用于给List结构集合注入的标签:
        list array set
      (2)用于个Map结构集合注入的标签:
      map props
    结构相同,标签可以互换

    业务层的接口实现类:AccountServiceImpl3.java

    package service.impl;
    
    
    import service.IAccountService;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Properties;
    import java.util.Set;
    import java.util.Map;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl3 implements IAccountService {
    
        private String[] myStrs;
        private List<String> myList;
        private Set<String> mySet;
        private Map<String,String> myMap;
        private Properties myProps;
    
        public void setMyStrs(String[] myStrs) {
            this.myStrs = myStrs;
        }
    
        public void setMyList(List<String> myList) {
            this.myList = myList;
        }
    
        public void setMySet(Set<String> mySet) {
            this.mySet = mySet;
        }
    
        public void setMyMap(Map<String, String> myMap) {
            this.myMap = myMap;
        }
    
        public void setMyProps(Properties myProps) {
            this.myProps = myProps;
        }
    
        public void  saveAccount(){
            System.out.println(Arrays.toString(myStrs));
            System.out.println(myList);
            System.out.println(mySet);
            System.out.println(myMap);
            System.out.println(myProps);
        }
    
    
    }

    bean.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <!--构造函数注入:
            使用的标签:constructor-arg
            标签出现的位置:bean标签的内部
            标签中的属性
                type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
                index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
                name:用于指定给构造函数中指定名称的参数赋值                                        常用的
                =============以上三个用于指定给构造函数中哪个参数赋值===============================
                value:用于提供基本类型和String类型的数据
                ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
    
            优势:
                在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
            弊端:
                改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
        -->
        <bean id="accountService" class="service.impl.AccountServiceImpl" scope="prototype">
            <constructor-arg name="name" value="泰斯特"></constructor-arg>
            <constructor-arg name="age" value="18"></constructor-arg>
            <constructor-arg name="birthday" ref="now"></constructor-arg>
        </bean>
    
        <!-- 配置一个日期对象 -->
        <bean id="now" class="java.util.Date"></bean>
    
        <!-- 复杂类型的注入/集合类型的注入
            用于给List结构集合注入的标签:
                list array set
            用于个Map结构集合注入的标签:
                map  props
            结构相同,标签可以互换
        -->
        <bean id="accountService3" class="service.impl.AccountServiceImpl3">
            <property name="myStrs">
                <set>
                    <value>AAA</value>
                    <value>BBB</value>
                    <value>CCC</value>
                </set>
            </property>
    
            <property name="myList">
                <array>
                    <value>AAA</value>
                    <value>BBB</value>
                    <value>CCC</value>
                </array>
            </property>
    
            <property name="mySet">
                <list>
                    <value>AAA</value>
                    <value>BBB</value>
                    <value>CCC</value>
                </list>
            </property>
    
            <property name="myMap">
                <props>
                    <prop key="testC">ccc</prop>
                    <prop key="testD">ddd</prop>
                </props>
            </property>
    
            <property name="myProps">
                <map>
                    <entry key="testA" value="aaa"></entry>
                    <entry key="testB">
                        <value>BBB</value>
                    </entry>
                </map>
            </property>
        </bean>
    
    </beans>

    表现层代码:

    package ui;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import service.IAccountService;
    import service.impl.AccountServiceImpl;
    
    /**
     * 模拟一个表现层,用于调用业务层
     */
    public class Client {
    
        /**
         * 获取spring的Ioc核心容器,并根据id获取对象
         *
         * ApplicationContext的三个常用实现类:
         *      ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用)
         *      FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须有访问权限)
         *
         *      AnnotationConfigApplicationContext:它是用于读取注解创建容器的,是明天的内容。
         *
         * 核心容器的两个接口引发出的问题:
         *  ApplicationContext:     单例对象适用              采用此接口
         *      它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。
         *
         *  BeanFactory:            多例对象使用
         *      它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。
         * @param args
         */
        public static void main(String[] args) {
            //1.获取核心容器对象
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    
            //2.根据id获取Bean对象,注意id是在bean.xml文件配置的
            IAccountService as  = (IAccountService)ac.getBean("accountService3");
            as.saveAccount();
    
    
        }
    }

    控制台输出:

        
  • 相关阅读:
    【模板】O(nlongn)求LIS
    【图论】用线段树写Dijikstra!!
    【图论】最短路总结
    【codeforces841A】Generous Kefa
    【模板】Tarjian求LCA
    【模板】 RMQ求区间最值
    【模板】map入门
    【二分 贪心】覆盖问题 BZOJ1052 HAOI2007
    【dp】10-15题解 snake vs block
    【模拟】10-15 题解 trans
  • 原文地址:https://www.cnblogs.com/luckyplj/p/11315903.html
Copyright © 2020-2023  润新知