• (四)Spring对IoC的实现



    Spring学习目录

    上一篇:(三)简单使用Spring

    下一篇:(五)Spring之Bean的作用域

    环境

    spring6里程碑版本的仓库
    依赖:spring context依赖、junit依赖、log4j2依赖
    log4j2.xml文件放到类路径下。

    IoC 控制反转

    控制反转是一种思想。
    控制反转是为了降低程序耦合度,提高程序扩展力,达到OCP原则,达到DIP原则。
    控制反转,反转的是什么?

    • 将对象的创建权利交出去,交给第三方容器负责。
    • 将对象和对象之间关系的维护权交出去,交给第三方容器负责。

    控制反转这种思想如何实现呢?
    DI(Dependency Injection):依赖注入

    依赖注入

    依赖注入实现了控制反转的思想。
    Spring通过依赖注入的方式来完成Bean管理的。
    Bean管理说的是:Bean对象的创建,以及Bean对象中属性的赋值(或者叫做Bean对象之间关系的维护)。
    依赖注入(Dependency Injection 简称DI):

    • 依赖:A对象和B对象的关系。
    • 注入:通过手段让A与B产生关系(依赖)。

    依赖注入常见的实现方式包括两种:

    • 1.set注入(执行set方法给属性赋值)
    • 2.构造方法注入(执行构造方法给属性赋值)

    set注入

    创建UserDao

    public class UserDao {
        //使用slf4j记录日志
        private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
        public void insert(){
            logger.info("新增用户数据");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    创建UserService
    必须提供set方法,Spring就会调用这个set方法,给userDao属性赋值,这里的set的方法可以随意,只需要以set开头即可,但是之后在spring配置文件配置set注入的时候就不能随便写了。这里先不按照规范写一个set方法测试。

    /**
     * set注入
     */
    public class UserService {
        private UserDao userDao;
        //提供set方法之后,还需要在配置文件里面配置
        public void setMyUserDao(UserDao xy){
            this.userDao = xy;
        }      
        public void saveUser(){
            System.out.println("set注入");
            userDao.insert();
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    创建spring.xml配置文件
    通过property标签进行set注入。

    • property标签:配置set注入
      • name属性:是set方法的方法名去掉”set“,然后首字母小写
      • ref属性:翻译为引用(references),指定的是要注入的bean的id
    <?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">
    
        <!--set注入-->
        <!--配置dao-->
        <bean id="userDaoBean" class="com.dependency.injection.dao.UserDao"/>
    
        <!--配置service-->
        <bean id="userServiceBean" class="com.dependency.injection.service.UserService">
            <property name="myUserDao" ref="userDaoBean"/>
        </bean>
        <bean id="carDaoBean" class="com.dependency.injection.dao.CarDao"></bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    测试程序:

        @Test
        public void testSetDI(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            UserService userServiceBean = applicationContext.getBean("userServiceBean", UserService.class);
            userServiceBean.saveUser();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述
    实现原理:

    • 1.通过property标签获取到set方法名称:setMyUserDao
    • 2.通过反射机制推断出属性名:userDao
     this.userDao = xy;
    
    • 1
    • 3.通过反射机制调用setUserDao()方法给属性赋值

    说明property标签的name是:setUserDao()方法名演变得到的。演变的规律是:

    • setUsername() 演变为 username
    • setPassword() 演变为 password
    • setUserDao() 演变为 userDao
    • setUserService() 演变为 userService

    一般情况下set方法名不会自定义,编写都是要符合java规范,也可以采用自动生成

    	private UserDao userDao;
    	public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
    • 1
    • 2
    • 3
    • 4

    所以spring.xml配置文件property标签的name就可以直接复制属性名

    	<property name="userDao" ref="userDaoBean"/>
    
    • 1

    构造注入

    核心原理:通过调用构造方法来给属性赋值。
    创建CarDao:

    public class CarDao {
        //使用slf4j记录日志
        private static final Logger logger = LoggerFactory.getLogger(CarDao.class);
        public void insert(){
            logger.info("新增汽车数据");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建CarService:
    提供构造方法

    /**
     * 构造注入
     */
    public class CarService {
        private UserDao userDao;
        private CarDao carDao;
    
        public CarService(UserDao userDao, CarDao carDao) {
            this.userDao = userDao;
            this.carDao = carDao;
        }
    
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        public void setCarDao(CarDao carDao) {
            this.carDao = carDao;
        }
    
        public void saveCar(){
            System.out.println("构造注入");
            userDao.insert();
            carDao.insert();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    创建spring2.xml配置文件:
    构造注入需要在这个文件配置,通过constructor-arg标签配置。

    • constructor-arg标签:配置构造注入
      • index属性:指定的参数下标,以0开始
      • name属性:指定参数的名字
      • ref属性:指定的是要注入的bean的id

    构造注入有三种配置方式:

    • 1.根据参数下标注入,使用index属性
    • 2.根据参数名字注入,使用name属性
    • 3.不指定参数下标和名字,Spring可以自己做自动类型匹配把ref注入
    <?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">
    
        <!--构造注入-->
        <!--配置dao-->
        <bean id="userDaoBean" class="com.dependency.injection.dao.UserDao"></bean>
        <bean id="carDaoBean" class="com.dependency.injection.dao.CarDao"></bean>
    
        <!--配置service-->
        <bean id="carServiceBean" class="com.dependency.injection.service.CarService">
            <!--根据参数下标注入-->
            <constructor-arg index="0" ref="userDaoBean" />
            <constructor-arg index="1" ref="carDaoBean" />
        </bean>
    
        <bean id="carServiceBean2" class="com.dependency.injection.service.CarService">
            <!--根据参数名字注入-->
            <constructor-arg name="userDao" ref="userDaoBean" />
            <constructor-arg name="carDao" ref="carDaoBean" />
        </bean>
    
        <bean id="carServiceBean3" class="com.dependency.injection.service.CarService">
            <!--不指定参数下标和名字,Spring可以自己做自动类型匹配把ref注入-->
            <constructor-arg ref="userDaoBean" />
            <constructor-arg ref="carDaoBean" />
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    测试程序:

        @Test
        public void testConstructorDI(){
    
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2.xml");
    
            //根据参数下标注入测试
            CarService carServiceBean = applicationContext.getBean("carServiceBean", CarService.class);
            carServiceBean.saveCar();
            //根据参数名字注入测试
            CarService carServiceBean2 = applicationContext.getBean("carServiceBean2", CarService.class);
            carServiceBean2.saveCar();
            //不指定参数下标和名字测试
            CarService carServiceBean3 = applicationContext.getBean("carServiceBean", CarService.class);
            carServiceBean3.saveCar();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    请添加图片描述

    set注入专题

    注入外部Bean

    注入外部Bean就是使用ref属性注入,上面的set注入就是一个外部Bean注入
    创建OrderDao:

    public class OrderDao {
        private static final Logger logger = LoggerFactory.getLogger(OrderDao.class);
        public void insert(){
            logger.info("生成订单。。。");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建OrderService:

    public class OrderService {
        private OrderDao orderDao;
    
        public void setOrderDao(OrderDao orderDao) {
            this.orderDao = orderDao;
        }
        public void  generate(){
            orderDao.insert();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    创建配置文件set-DI.xml

    <!--
            注入外部Bean:在property标签使用ref属性注入
        -->
        <!--定义Bean-->
        <bean id="orderDaoBean" class="com.dependency.injection.dao.setDI.OrderDao"/>
        <bean id="orderServiceBean" class="com.dependency.injection.service.setDI.OrderService">
            <!--注入外部Bean:使用ref属性注入-->
            <property name="orderDao" ref="orderDaoBean"/>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试程序:

        @Test
        public void testSetDI2(){
            //外部Bean测试
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-DI.xml");
            OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
            orderServiceBean.generate();
    
            
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    请添加图片描述

    注入内部Bean(了解)

    在property标签嵌套bean标签注入,称为内部Bean
    在set-DI.xml配置:

    	<!--
            注入内部Bean
        -->
        <bean id="orderServiceBean2" class="com.dependency.injection.service.setDI.OrderService">
            <property name="orderDao">
                <bean class="com.dependency.injection.dao.setDI.OrderDao"/>
            </property>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试程序:

        @Test
        public void testSetDI2(){
            //外部Bean测试
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-DI.xml");
            OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
            orderServiceBean.generate();
    
            //内部Bean测试
            OrderService orderServiceBean2 = applicationContext.getBean("orderServiceBean2", OrderService.class);
            orderServiceBean2.generate();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    请添加图片描述

    注入简单类型

    我们之前在进行注入的时候,对象的属性是另一个对象。使用的是一个ref属性。
    如果我们注入的是一个int类型,我们就需要使用value属性赋值。
    注入简单类型,Spring规定了哪些是简单类型呢,进入源码可以看一下BeanUtils工具类

    public static boolean isSimpleValueType(Class<?> type) {
                return Void.class != type && Void.TYPE != type &&
                (ClassUtils.isPrimitiveOrWrapper(type) ||
                Enum.class.isAssignableFrom(type) ||
                CharSequence.class.isAssignableFrom(type) ||
                Number.class.isAssignableFrom(type) ||
                Date.class.isAssignableFrom(type) ||
                Temporal.class.isAssignableFrom(type) ||
                URI.class == type ||
                URL.class == type ||
                Locale.class == type ||
                Class.class == type);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    分别包括:

    • isPrimitiveOrWrapper:基本类型或其对应的包装类
    • Enum:枚举类型
    • CharSequence: 字符接口,凡是实现了字符接口都为简单类型,String实现了该接口,所以String为简单类型
    • Number:数字类型,凡是继承这个抽象类,都为简单类型
    • Date:日期类型
    • Temporal:时间和时区接口,这个是java8以后的新特性
    • URI:uri类
    • URL:url类
    • Locale:语言类,例如英文、中文等等
    • Class:class类

    需要注意的是Date类型,想要使用Value进行赋值的话,这个value是有格式要求的。例如
    这种格式是无法转换成java.util.Date类型的

    <property name="birth" value="2020-11-11"/>
    
    • 1

    需要以下特定格式:

    <property name="birth" value="Wed Nov 02 18:47:56 CST 2022"/>
    
    • 1

    但是这个格式是外国人看得比较舒服的格式,中国人看不习惯,所以,在实际开发中,不会把这个Date当作简单类型,一般采用ref进行赋值

    我们来测试以下简单类型的注入
    枚举类:

    /**
     * 表示季节
     */
    public enum Season {
        SPRING,SUMMER,AUTUMN,WINTER
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建SimpleValueType类:

    /**
     * 测试简单类型
     */
    public class SimpleValueType {
        //基本类型及其包装类
    
        private boolean flag;
        private Boolean flag2;
    
        private char c;
        private Character c2;
    
        //枚举类型
        private Season season;
        //CharSequence
        private String username;
    
        //Number
        private int age;
        private Integer age2;
    
        //Class
        private Class clazz;
    
        //Date
        private Date birth;
    
        @Override
        public String toString() {
            return "SimpleValueType{" +
                    "flag=" + flag +
                    ", flag2=" + flag2 +
                    ", c=" + c +
                    ", c2=" + c2 +
                    ", season=" + season +
                    ", username='" + username + '\'' +
                    ", age=" + age +
                    ", age2=" + age2 +
                    ", clazz=" + clazz +
                    ", birth=" + birth +
                    '}';
        }
    
        public void setBirth(Date birth) {
            this.birth = birth;
        }
    
        public void setFlag(boolean flag) {
            this.flag = flag;
        }
    
        public void setFlag2(Boolean flag2) {
            this.flag2 = flag2;
        }
    
        public void setC(char c) {
            this.c = c;
        }
    
        public void setC2(Character c2) {
            this.c2 = c2;
        }
    
        public void setSeason(Season season) {
            this.season = season;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public void setAge2(Integer age2) {
            this.age2 = age2;
        }
    
        public void setClazz(Class clazz) {
            this.clazz = clazz;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 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
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    set-DI.xml文件配置

     <!--测试简单类型-->
        <bean id="svtBean" class="com.dependency.injection.bean.SimpleValueType">
            <property name="age" value="20"/>
            <property name="age2" value="20"/>
            <property name="username" value="张三"/>
            <property name="season" value="SPRING"/>
            <property name="flag" value="false"/>
            <property name="flag2" value="true"/>
            <property name="c" value="男"/>
            <property name="c2" value="女"/>
            <property name="clazz" value="java.lang.String"/>
            <property name="birth" value="Wed Nov 02 18:47:56 CST 2022"/>
            <!--这个格式是外国人看得比较舒服的格式,中国人看不习惯,所以,在实际开发中,不会把这个Date当作简单类型,一般采用ref进行赋值-->
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试程序:

        @Test
        public void testSimpleTypeSet(){
            //简单类型
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-DI.xml");
            SimpleValueType svtBean = applicationContext.getBean("svtBean", SimpleValueType.class);
            System.out.println(svtBean);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    请添加图片描述

    经典案例:给数据源的属性注入值

    简单类型注入有什么用呢?
    假设我们现在要自己手写一个数据源,我们都知道所有的数据源都要实现javax.sql.DataSource接口,并且数据源中应该有连接数据库的信息,例如:driver、url、username、password等。可以让Spring容器管理数据源

    /**
     * 把数据源交给Spring容器管理
     */
    public class MyDataSource implements DataSource {
        private String driver;
        private String url;
        private String username;
        private String password;
    
        @Override
        public String toString() {
            return "MyDataSource{" +
                    "driver='" + driver + '\'' +
                    ", url='" + url + '\'' +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    
        public void setDriver(String driver) {
            this.driver = driver;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            return null;
        }
    
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return null;
        }
    
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter out) throws SQLException {
    
        }
    
        @Override
        public void setLoginTimeout(int seconds) throws SQLException {
    
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            return null;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return null;
        }
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 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
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    set-DI.xml配置:

        <bean id="myDataSource" class="com.dependency.injection.jdbc.MyDataSource">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/spring"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试程序:

        @Test
        public void testMyDataSource(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-DI.xml");
            MyDataSource myDataSource = applicationContext.getBean("myDataSource", MyDataSource.class);
            System.out.println(myDataSource);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    级联属性赋值(了解)

    创建Clazz班级类:

    /**
     * 班级,级联赋值
     */
    public class Clazz {
        private String name;//班级名称
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Clazz{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    创建Student学生类:

    /**
     * 学生,级联赋值
     */
    public class Student {
        private String name;
    
        private Clazz clazz;//学生属于哪个班级
    
        public void setClazz(Clazz clazz) {
            this.clazz = clazz;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Clazz getClazz() {
            return clazz;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", clazz=" + clazz +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    创建cascade.xml配置文件:
    级联赋值,需要有两个注意点:

    • 1.这种情况Student里面还想要提供这个clazz属性的get方法
    • 2.这种方式赋值,想要保证clazz有值,也就是说先配置clazz的注入信息,再进行赋值,顺序不能颠倒。Spring觉得必须符合先有对象,再有值。
    <?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="studentBean" class="com.dependency.injection.bean.Student">
            <property name="name" value="张三"/>
            <property name="clazz" ref="clazzBean" />
           	<!--这里的顺序不能颠倒,并且保证Student类里有getName方法-->
            <property name="clazz.name" value="高三二班" />
        </bean>
    
        <!--<bean id="clazzBean" class="com.dependency.injection.bean.Clazz">
            <property name="name" value="高三一班"/>
        </bean>-->
        <bean id="clazzBean" class="com.dependency.injection.bean.Clazz"></bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    测试程序:

        @Test
        public void testCascade(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("cascade.xml");
            Clazz clazzBean = applicationContext.getBean("clazzBean", Clazz.class);
    
            Student studentBean = applicationContext.getBean("studentBean", Student.class);
            System.out.println(studentBean);
            System.out.println(clazzBean);
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    请添加图片描述

    注入数组

    简单类型数组注入

    创建Arrays类

    /**
     * 注入数组
     */
    public class Arrays {
        private String[] like;//爱好
        public void setLike(String[] like) {
            this.like = like;
        }
        @Override
        public String toString() {
            return "Arrays{" +
                    "like=" + java.util.Arrays.toString(like) +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    创建SpringArray.xml文件配置:
    属性是简单类型,并且是数组,property标签里面使用array标签套value标签,value标签里面输入值

    <!--数组注入-->
        <bean id="arrayBean" class="com.dependency.injection.bean.Arrays">
            <property name="like">
                <array>
                    <value></value>
                    <value></value>
                    <value>rap</value>
                </array>
            </property>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试程序:

        @Test
        public void testArrays(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringArray.xml");
            Arrays arrayBean = applicationContext.getBean("arrayBean", Arrays.class);
            System.out.println(arrayBean);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    非简单类型数组注入

    创建朋友类:

    /**
     * 朋友类,注入数组
     */
    public class Friend {
        private String name;
    
        @Override
        public String toString() {
            return "Friend{" +
                    "name='" + name + '\'' +
                    '}';
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    修改Arrays类:

    /**
     * 注入数组
     */
    public class Arrays {
        private String[] like;//爱好
    
        //多个朋友
        private Friend[] friends;
    
        public void setFriends(Friend[] friends) {
            this.friends = friends;
        }
    
        @Override
        public String toString() {
            return "Arrays{" +
                    "like=" + java.util.Arrays.toString(like) +
                    ", friends=" + java.util.Arrays.toString(friends) +
                    '}';
        }
    
        public void setLike(String[] like) {
            this.like = like;
        }
    
        /*@Override
        public String toString() {
            return "Arrays{" +
                    "like=" + java.util.Arrays.toString(like) +
                    '}';
        }*/
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    修改SpringArray.xml配置文件:
    不是简单类型,且是数组
    需要提前创建好Friend的bean,使用array标签,套ref标签,在bean属性中填Friend的id

    	<bean id="arrayBean" class="com.dependency.injection.bean.Arrays">
            <property name="like">
                <array>
                    <value></value>
                    <value></value>
                    <value>rap</value>
                </array>
            </property>
            <property name="friends">
                <array>
                    <ref bean="friendBean1"/>
                    <ref bean="friendBean2"/>
                    <ref bean="friendBean3"/>
                </array>
            </property>
        </bean>
        <bean id="friendBean1" class="com.dependency.injection.bean.Friend">
            <property name="name" value="张三"/>
        </bean>
    
        <bean id="friendBean2" class="com.dependency.injection.bean.Friend">
            <property name="name" value="李四"/>
        </bean>
    
        <bean id="friendBean3" class="com.dependency.injection.bean.Friend">
            <property name="name" value="王五"/>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    再次运行测试程序:
    请添加图片描述

    注入集合

    注入List集合

    创建Collection类

    /**
     * 注入集合
     */
    public class Collection {
        //注入List集合
        private List<String> names;
        
        public void setNames(List<String> names) {
            this.names = names;
        }
    
        @Override
        public String toString() {
            return "Collection{" +
                    "names=" + names +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    创建spring-collection.xml配置:
    注入List集合,与注入数组类似,简单类型使用list标签套value标签,非简单类型就套ref标签
    这里演示简单类型
    List集合:有序可重复

    <bean id="collectionBean" class="com.dependency.injection.bean.Collection">
            
            <property name="names">
            	<!--注入List集合-->
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                    <value>赵六</value>
                    <value>赵六</value>
                </list>
            </property>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试程序:

        @Test
        public void testCollection(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-collection.xml");
            Collection collectionBean = applicationContext.getBean("collectionBean", Collection.class);
            System.out.println(collectionBean);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    注入Set集合

    修改Collection类:

    /**
     * 注入集合
     */
    public class Collection {
        //注入List集合
        private List<String> names;
        //注入Set集合
        private Set<String> addrs;
        
        @Override
        public String toString() {
            return "Collection{" +
                    "names=" + names +
                    ", addrs=" + addrs +
                    '}';
        }
    
        public void setNames(List<String> names) {
            this.names = names;
        }
        public void setAddrs(Set<String> addrs) {
            this.addrs = addrs;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    修改spring-collection.xml配置:
    注入Set集合,也是与数组差不多,简单类型使用set标签套value标签,非简单类型就套ref标签
    这里演示简单类型
    Set集合:无序不可重复

    <bean id="collectionBean" class="com.dependency.injection.bean.Collection">
            <!--注入List集合-->
            <property name="names">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                    <value>赵六</value>
                    <value>赵六</value>
                </list>
            </property>
            <!--注入Set集合-->
            <property name="addrs">
                <set>
                    <value>上海</value>
                    <value>北京</value>
                    <value>广州</value>
                    <value>广州</value>
                </set>
            </property>                 
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    再次运行测试程序,发现没有两个广州,无序不可重复
    在这里插入图片描述

    注入Map集合

    修改Collection类:

    /**
     * 注入集合
     */
    public class Collection {
        //注入List集合
        private List<String> names;
        //注入Set集合
        private Set<String> addrs;
        //注入Map
        private Map<Integer,String> phones;
    
        
        @Override
        public String toString() {
            return "Collection{" +
                    "names=" + names +
                    ", addrs=" + addrs +
                    ", phones=" + phones +
                    '}';
        }
    
        public void setPhones(Map<Integer, String> phones) {
            this.phones = phones;
        }
       
    
        public void setNames(List<String> names) {
            this.names = names;
        }
    
        
        public void setAddrs(Set<String> addrs) {
            this.addrs = addrs;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    修改spring-collection.xml配置:
    注入Map集合 使用map标签套entry标签

    • 如果是简单类型,则entry标签的属性使用key和value
    • 如果非简单类型,则entry标签的属性使用key-ref和value-ref

    key是无序不可重复,value有序可重复
    注意:如果key或key-ref没有输入值的话,默认会是null,且只能有一个null

        <!--集合注入-->
        <bean id="collectionBean" class="com.dependency.injection.bean.Collection">
            <!--注入List集合-->
            <property name="names">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                    <value>赵六</value>
                    <value>赵六</value>
                </list>
            </property>
            <!--注入Set集合-->
            <property name="addrs">
                <set>
                    <value>上海</value>
                    <value>北京</value>
                    <value>广州</value>
                    <value>广州</value>
                </set>
            </property>
            <!--注入Map集合-->
            <property name="phones">
                <map>
                    <entry key="1" value="110"/>
                    <entry key="2" value="111"/>
                    <entry key="3" value="119"/>
                    <entry key="" value="120"/>
                </map>
            </property>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    再次运行程序
    请添加图片描述

    注入Properties

    注入Properties属性类,Properties本质上也是Map集合,
    /因为它的父类是一个Hashtbale实现了Map接口。但是注入方式不一样,Properties的key和value的类型只能是String
    修改Collection类:

    /**
     * 注入集合
     */
    public class Collection {
        //注入List集合
        private List<String> names;
        //注入Set集合
        private Set<String> addrs;
        //注入Map
        private Map<Integer,String> phones;
    
        //注入Properties
        private Properties properties;
        
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    
        
    
        @Override
        public String toString() {
            return "Collection{" +
                    "names=" + names +
                    ", addrs=" + addrs +
                    ", phones=" + phones + "\n" +
                    ", properties=" + properties +
                    '}';
        }
        
    
        public void setPhones(Map<Integer, String> phones) {
            this.phones = phones;
        }
        
    
        public void setNames(List<String> names) {
            this.names = names;
        }
    
        
        public void setAddrs(Set<String> addrs) {
            this.addrs = addrs;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    修改spring-collection.xml配置:
    注入Properties属性类

    • 使用props标签套prop标签
    • key写在prop标签key的属性里面,value写在prop标签里面

    注意:与map不一样key如果没写值,它就不是null,它是真的为空–“”

       <bean id="collectionBean" class="com.dependency.injection.bean.Collection">
            <!--注入List集合-->
            <property name="names">
                <list>
                    <value>张三</value>
                    <value>李四</value>
                    <value>王五</value>
                    <value>赵六</value>
                    <value>赵六</value>
                </list>
            </property>
            <!--注入Set集合-->
            <property name="addrs">
                <set>
                    <value>上海</value>
                    <value>北京</value>
                    <value>广州</value>
                    <value>广州</value>
                </set>
            </property>
            <!--注入Map集合 -->
            <property name="phones">
                <map>
                    <entry key="1" value="110"/>
                    <entry key="2" value="111"/>
                    <entry key="3" value="119"/>
                    <entry key="" value="120"/>
                </map>
            </property>
            <!--注入Properties属性类-->
            <property name="properties">
                <props>
                    <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
                    <prop key="url">jdbc:mysql://localhost:3306/spring</prop>
                    <prop key="username">root</prop>
                    <prop key="password">123456</prop>
                    <prop key=""></prop>
                </props>
            </property>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    再次运行测试程序:
    请添加图片描述

    注入null和空字符串

    创建Empty类

    /**
     * 注入null或空字符串
     */
    public class Empty {
        //注入null
        private String name1;
        private String name2;
        
        //注入空字符串
        private String name3;
        private String name4;
        
        
    
        public void setName1(String name1) {
            this.name1 = name1;
        }
    
        public void setName2(String name2) {
            this.name2 = name2;
        }
    
        public void setName3(String name3) {
            this.name3 = name3;
        }
    
        public void setName4(String name4) {
            this.name4 = name4;
        }
    
        @Override
        public String toString() {
            return "Empty{" +
                    "name1='" + name1 + '\'' +
                    ", name2='" + name2 + '\'' +
                    ", name3='" + name3 + '\'' +
                    ", name4='" + name4 + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    创建spring-empty.xml配置:
    注入null,两种方式

    • 不给name属性赋值
    • 或者在property里面使用null标签

    注意:如果在value里面写一个null,这是赋值一个字符串null,而不是一个真正的null

    注入空字符串,两种方式

    • 不给value赋值,默认为空字符串
    • 或者在property里面使用value标签,不给这个标签赋值
        <!--
            注入null或空字符串
        -->
    
        <bean id="emptyBean" class="com.dependency.injection.bean.Empty">
    
            <!--注入null,name2不赋值-->
            <property name="name1">
                <null/>
            </property>
            
            <!--注入空字符串-->
            <property name="name3" value=""/>
            <property name="name4">
                <value/>
            </property>
    
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    测试程序:

        @Test
        public void testEmpty(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-empty.xml");
            Empty emptyBean = applicationContext.getBean("emptyBean", Empty.class);
            System.out.println(emptyBean);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    注入特殊字符

    XML中有5个特殊字符,分别是:<、>、'、"、&
    以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错。
    解决方案包括两种:
    第一种方案:特殊符号使用转义字符(实体符号)代替。
    第二种方案:使用CDATA[]]>,因为放在CDATA区中的数据不会被XML文件解析器解析。它会把里面的内容当中一个普通字符串处理。

    注意:使用,不能在property使用value属性了,只能嵌套一个value标签

    5个特殊字符对应的转义字符分别是:

    特殊字符转义字符
    >>
    <<
    '
    ""
    &&

    创建MathBean类:

    /**
     * 注入特殊字符
     */
    public class MathBean {
        private String result1;//使用转义字符
        private String result2;//使用
    
        public void setResult1(String result1) {
            this.result1 = result1;
        }
    
        public void setResult2(String result2) {
            this.result2 = result2;
        }
    
        @Override
        public String toString() {
            return "MathBean{" +
                    "result1='" + result1 + '\'' +
                    ", result2='" + result2 + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    创建spring-special.xml:

     <!--注入特殊字符-->
        <bean id="mathBean" class="com.dependency.injection.bean.MathBean">
            <property name="result1" value="2 < 3"/>
            <property name="result2">
                <value><![CDATA[2 < 3]]></value>
            </property>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    测试程序:

        @Test
        public void testSpecial(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-special.xml");
            MathBean mathBean = applicationContext.getBean("mathBean", MathBean.class);
            System.out.println(mathBean);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    p命名空间注入

    目的:简化配置。
    创建P类

    /**
     * p命名空间注入
     */
    public class P {
        private String name;
    
        private int age;
    
        private Date birth;
    
        @Override
        public String toString() {
            return "P{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", birth=" + birth +
                    '}';
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public void setBirth(Date birth) {
            this.birth = birth;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    创建spring-p.xml配置:
    p命名空间注入,底层还是set注入,只不过p命名空间注入可以让spring配置变得更加简单。
    使用步骤:

    • 第一步:使用p命名空间,需要在beans标签加上一个配置
      xmlns:p=“http://www.springframework.org/schema/p”
    • 第二步:在bean标签使用即可,普通类型使用p:属性名=“属性值”,非简单类型使用p:属性名-ref=“bean的id”
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
           
        <bean id="pBean" class="com.dependency.injection.bean.P" p:age="20" p:name="张三" p:birth-ref="birthBean"/>
        <bean id="birthBean" class="java.util.Date"/>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试程序:

        @Test
        public void testP(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spting-p.xml");
            P pBean = applicationContext.getBean("pBean", P.class);
            System.out.println(pBean);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    c命名空间注入

    目的:简化配置。
    创建C类:

    /**
     * c命名空间注入
     */
    public class C {
        private String name;
        private int age;
        private Date birth;
    
        public C(String name, int age, Date birth) {
            this.name = name;
            this.age = age;
            this.birth = birth;
        }
    
        @Override
        public String toString() {
            return "C{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", birth=" + birth +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    创建spring-c.xml配置:
    c命名空间注入,底层还是基于构造方法注入的,c命名空间注入是用来简化构造注入的
    使用步骤:

    • 第一步:与p命名空间一样,需要在上面beans标签加上一个配置
      xmlns:c=“http://www.springframework.org/schema/c”

    • 第二步:在bean标签使用即可

      • 简单类型:根据下标:c:_下标=“属性值”,根据属性名:c:属性名=“属性值”

      • 非简单类型:根据下标:c:_下标-ref=“属性值”,根据属性名:c:属性名-ref=“属性值”

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
           
        <bean id="cBean" class="com.dependency.injection.bean.C" c:_0="张三" c:age="20" c:birth-ref="birthBean"/>
        <bean id="birthBean" class="java.util.Date"/>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    测试程序:

        @Test
        public void testC(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-c.xml");
            C cBean = applicationContext.getBean("cBean", C.class);
            System.out.println(cBean);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    util命名空间

    util命名空间注入,主要是让配置复用。
    例如写两个数据源,都是同样的配置,就可以使用utils
    创建数据源MyDataSource1类:

    /**
     * 把数据源交给Spring容器管理
     */
    public class MyDataSource1 implements DataSource {
        private Properties properties;
    
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    
        @Override
        public String toString() {
            return "MyDataSource1{" +
                    "properties=" + properties +
                    '}';
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            return null;
        }
    
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return null;
        }
    
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter out) throws SQLException {
    
        }
    
        @Override
        public void setLoginTimeout(int seconds) throws SQLException {
    
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            return null;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return null;
        }
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return false;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    创建数据源MyDataSource2类:

    /**
     * 把数据源交给Spring容器管理
     */
    public class MyDataSource2 implements DataSource {
        private Properties properties;
    
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    
        @Override
        public String toString() {
            return "MyDataSource1{" +
                    "properties=" + properties +
                    '}';
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            return null;
        }
    
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return null;
        }
    
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter out) throws SQLException {
    
        }
    
        @Override
        public void setLoginTimeout(int seconds) throws SQLException {
    
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            return null;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return null;
        }
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return false;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    创建spring-util.xml配置:

    • 第一步:使用utils命名空间,需要在上面beans标签加上两个配置
    xmlns:utils="http://www.springframework.org/schema/util"
    
    • 1

    xsi里面添加,用来约束xml文件的

    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
    
    • 1
    • 第二步:配置相关的util标签

    • 第三步:在property里面用ref属性进行复用

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
        <util:properties id="properties">
            <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
            <prop key="url">jdbc:mysql://localhost:3306/spring</prop>
            <prop key="username">root</prop>
            <prop key="password">123456</prop>
        </util:properties>
        <!--数据源1-->
        <bean id="ds1" class="com.dependency.injection.jdbc.MyDataSource1">
            <property name="properties" ref="properties"/>
        </bean>
    
        <!--数据源2-->
        <bean id="ds2" class="com.dependency.injection.jdbc.MyDataSource2">
            <property name="properties" ref="properties"/>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    测试程序:

        @Test
        public void testUtil(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-util.xml");
            MyDataSource1 ds1 = applicationContext.getBean("ds1", MyDataSource1.class);
            MyDataSource2 ds2 = applicationContext.getBean("ds2", MyDataSource2.class);
            System.out.println(ds1);
            System.out.println(ds2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    请添加图片描述

    基于XML的自动装配

    Spring还可以完成自动化的注入,自动化注入又被称为自动装配。它可以根据名字进行自动装配,也可以根据类型进行自动装配。
    自动装配也是基于set方式实现的。

    根据名称自动装配

    还是使用之前的OrderDao和OrderService
    创建spring-outowire.xml配置:
    根据名称自动装配

    • 第一步:需要在bean标签配置属性autowire=“byName”
    • 第二步:被注入的bean的id就不能随便写了,必须写set方法,去掉set,然后首字母小写。
    <bean id="orderDao" class="com.dependency.injection.dao.setDI.OrderDao"/>
    <bean id="orderService" class="com.dependency.injection.service.setDI.OrderService" autowire="byName"></bean>
    
    • 1
    • 2

    请添加图片描述

    根据类型自动装配

    还是使用之前的UserDao、UserService

    修改spring-outowire.xml:
    根据类型自动装配
    只需要在bean标签配置属性autowire=“byType”

    注意:根据类型自动装配的使用,在有效的配置文件当中,某种类型的实例只能有一个,也就是说某种类型的bean只能有一个。
    例如配置以下程序之后会报错:
    在这里插入图片描述

    因为在之前的配置文件有UserDao的bean对象,Spring“晕了”,不知道哪个bean是需要注入。
    把之前的bean对象注释掉即可

    	 <!--根据名称自动装配-->
    	<bean id="orderDao" class="com.dependency.injection.dao.setDI.OrderDao"/>
        <bean id="orderService" class="com.dependency.injection.service.setDI.OrderService" autowire="byName"></bean>
        <!--根据类型自动装配-->
        <bean class="com.dependency.injection.dao.UserDao"/>   
        <bean id="userDaoBean" class="com.dependency.injection.service.UserService" autowire="byType"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试程序:

        @Test
        public void testOutowrieByType(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-outowire.xml");
            UserService userService = applicationContext.getBean("userDaoBean", UserService.class);
            userService.saveUser();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述

    Spring引入外部属性配置文件

    引入外部的properties文件
    创建数据源MyDataSource3类:

    public class MyDataSource3 implements DataSource {
        private String driver;
        private String url;
        private String username;
        private String password;
    
        @Override
        public String toString() {
            return "MyDataSource{" +
                    "driver='" + driver + '\'' +
                    ", url='" + url + '\'' +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    
        public void setDriver(String driver) {
            this.driver = driver;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            return null;
        }
    
        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return null;
        }
    
        @Override
        public PrintWriter getLogWriter() throws SQLException {
            return null;
        }
    
        @Override
        public void setLogWriter(PrintWriter out) throws SQLException {
    
        }
    
        @Override
        public void setLoginTimeout(int seconds) throws SQLException {
    
        }
    
        @Override
        public int getLoginTimeout() throws SQLException {
            return 0;
        }
    
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            return null;
        }
    
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException {
            return null;
        }
    
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException {
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 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
    • 75
    • 76
    • 77

    jdbc.properties文件:

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/spring
    username=root
    password=123456
    
    • 1
    • 2
    • 3
    • 4

    创建spring-properties.xml配置:
    引入外部的properties文件

    • 第一步:引入context命名空间。
    xmlns:context="http://www.springframework.org/schema/context"
    
    • 1

    在xsi引入 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

    • 第二步:使用context:property-placeholder标签location属性的引入,location是默认从类的根路径加载。
    <context:property-placeholder location="jdbc.properties"/>
    
    • 1
    • 第三步:在property标签的value属性使用${key}进行取值。
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
                               
        <context:property-placeholder location="jdbc.properties"/>
        <bean id="myDataSource" class="com.dependency.injection.jdbc.MyDataSource3">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    测试程序:

        @Test
        public void testProperties(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-properties.xml");
            MyDataSource3 myDataSource = applicationContext.getBean("myDataSource", MyDataSource3.class);
            System.out.println(myDataSource);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    请添加图片描述
    运行后发现username居然不是root,而是shinle,而我的电脑名称也是shinle,是不是很巧。

    请添加图片描述
    这是因为${}进行加载的时候,Spring默认加载的是电脑的系统环境,所以配置文件一般都会加一个前缀。

    jdbc.properties文件:

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/spring
    jdbc.username=root
    jdbc.password=123456
    
    • 1
    • 2
    • 3
    • 4

    spring-properties.xml配置文件改为:

    	<context:property-placeholder location="jdbc.properties"/>
        <bean id="myDataSource" class="com.dependency.injection.jdbc.MyDataSource3">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    再次运行:
    请添加图片描述

  • 相关阅读:
    debian 修改镜像源为阿里云【详细步骤】
    【计算机网络】https协议
    收银系统源码推荐-千呼新零售
    基于Java毕业设计高校共享机房管理系统的设计与实现源码+系统+mysql+lw文档+部署软件
    是德科技keysight 33621A波形发生器
    【Rust日报】2022-11-03 - 《连线(Wired)》杂志:接管技术的“病毒式”安全编程语言...
    LDO基础知识
    OpenCV系列文章目录(持续更新中......)
    web前端课程设计(HTML和CSS实现餐饮美食文化网站)静态HTML网页制作
    [ROS](12)ROS通信 —— 参数服务器(Parameter Server)通信
  • 原文地址:https://blog.csdn.net/weixin_45832694/article/details/127848769