[000-01-010].第05节:DI实现的两种方式

我的后端学习大纲

我Spring学习大纲


1.Set注入实现DI:

set注入:基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值。这种方式要求属性必须对外提供set方法

1.1.编码实现:

a.新建模块:

在这里插入图片描述

b.pom.xml引入依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.powernode</groupId>
    <artifactId>spring6-002-dependency-injection</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <repositories>
        <repository>
            <id>repository.spring.milestone</id>
            <name>Spring Milestone Repository</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.0-M2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

</project>

c.引入实体类:

  • 1.UserDao.java
package com.jianqun.dao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserDao {

    private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
    public void insert(){
        logger.info("数据库正在保存用户信息");
    }
}
  • 2.UserService.java:
package com.jianqun.service;
import com.jianqun.dao.UserDao;
public class UserService {
    private UserDao userDao;
    //set注入的话,必须提供一个set方法
    //Spring容器会使用这个set方法来给userDao属性赋值
    
    //我自己写一个set方法,不使用IDEA工具自动生成的。就是不太符合javaBean规范
    //我是为了测试某个属性要写什么值来方便说明才这么干的
    public void setMySQLUserDao(UserDao xyz){
        this.userDao = xyz;
    }
    
    // 这个是IDEA工具自动生成的set方法,符合javaBean规范
    //public void setUserDao(UserDao userDao) {
    //    this.userDao = userDao;
    //}
    
    public void saveUser(){
        //保存用户信息方法,
        userDao.insert();
    }
}

d.编写配置文件:

  • 1.spring.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="userDaoBean" class="com.jianqun.dao.UserDao"/>

    <bean id="userServiceBean" class="com.jianqun.service.UserService">
        <!--
      	想要Spring调用对应的set方法,需要配置property标签
      	name属性怎么写指定的值:set方法的方法名,去掉set,然后把剩下的单词首字母小写,写在这里就可以了
      	ref属性:翻译为引用,ref后面指定的是要注入bean的id
		-->
        <property name="mySQLUserDao" ref="userDaoBean"></property>
    </bean>
</beans>

e.测试程序:

package com.jianqun.jianqun.bean;

import com.jianqun.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestUserService {

    @Test
    public void testSetDi(){
        // 初始化Spring容器上下文(解析beans.xml文件,创建所有的bean对象)
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
        // 根据id获取bean对象
        UserService userServiceBean = applicationContext.getBean("userServiceBean", UserService.class);
        userServiceBean.saveUser();
    }
}

在这里插入图片描述


1.2.实现原理:

a.原理推断:

<?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="userDaoBean" class="com.jianqun.dao.UserDao"/>

    <bean id="userServiceBean" class="com.jianqun.service.UserService">
        <!--
      	想要Spring调用对应的set方法,需要配置property标签
      	name属性怎么写指定的值:set方法的方法名,去掉set,然后把剩下的单词首字母小写,写在这里就可以了
      	ref属性:翻译为引用,ref后面指定的是要注入bean的id
		-->
        <property name="mySQLUserDao" ref="userDaoBean"></property>
    </bean>
</beans>
  • 1.获取property标签name属性的值:mySQLUserDao
  • 2.通过这个值推断出set方法名:setMySQLUserDao
  • 3.通过反射机制调用setMySQLUserDao()方法给属性赋值
  • 5.property标签的ref是要注入的bean对象的id。(通过ref属性来完成bean的装配,这是bean最简单的一种装配方式。装配指的是:创建系统组件之间关联的动作)

b.可以把set方法注释掉,再测试一下:

在这里插入图片描述

  • 1.通过测试得知,底层实际上调用了setUserDao()方法。所以需要确保这个方法的存在。现在我们把属性名修改一下,但方法名还是setUserDao(),我们来测试一下:
package com.powernode.spring6.service;

import com.powernode.spring6.dao.UserDao;

/**
 **/
public class UserService {

    private UserDao aaa;

    // 使用set方式注入,必须提供set方法。
    // 反射机制要调用这个方法给属性赋值的。
    public void setUserDao(UserDao userDao) {
        this.aaa = userDao;
    }

    public void save(){
        aaa.insert();
    }
}

在这里插入图片描述

  • 2.通过测试看到程序仍然可以正常执行,说明property标签的name是:setUserDao()方法名演变得到的。演变的规律是:
    • setUsername() 演变为 username
    • setPassword() 演变为 password
    • setUserDao() 演变为 userDao
    • setUserService() 演变为 userService
  • 3.另外,对于property标签来说,ref属性也可以采用标签的方式,但使用ref属性是多数的:
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
  <property name="userDao">
    <ref bean="userDaoBean"/>
  </property>
</bean>

总结:set注入的核心实现原理:通过反射机制调用set方法来给属性赋值,让两个对象之间产生关系


1.3.set注入专题:

在日常开发中,使用set注入的情况比较多,所以我们就以set注入作为专题来记录了

a.注入外部bean:

a1.特点:
  • 1.bean定义到外面,在property标签中使用ref属性进行注入。通常这种方式是常用
a2.案例1:
  • 1.OrderDao.java
    在这里插入图片描述

  • 2.定义orderService.java:
    在这里插入图片描述

  • 3.配置文件:
    在这里插入图片描述

  • 4.测试用例:
    在这里插入图片描述
    在这里插入图片描述

a3.案例2:

1.有两个类 service 类和dao类,在 service 调用 dao 里面的方法 ,在 spring 配置文件中进行配置

  • 1.创建UserDao接口
    在这里插入图片描述

  • 2.创建Dao接口的实现类:
    在这里插入图片描述

  • 3.创建UserService类:
    在这里插入图片描述

我们想实现的是在UserService中调用UserDao方法—>传统方式:

在这里插入图片描述

在Spring中实现的方式:

  • 1.现在我们使用了Spring,那么原始方式就就舍弃了,使用Spring来实现的话,就是通过在Spring的配置中来实现,在UserService中把Dao注入进去,在配置文件中,创建两个类的对象;
    <?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">
        <!-- 创建service对象--><bean id="userService" class="com.jianqun.Spring5_4.service.UserService">
        
        </bean>
           <!--创建dao对象-->
    	<bean id="userDaoImpl" class="com.jianqun.Spring5_4.dao.UserDaoImpl">	
    	   
    	</bean>
    </beans>
    
  • 2.把userDao对象注入UsrService就可以了(在注入的时候,相当于注入一个对象)
    <?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="userDaoImpl" class="com.jianqun.Spring5_4.dao.UserDaoImpl"></bean>
    		
    	    <!-- 创建service对象-->
    	    <bean id="userService" class="com.jianqun.Spring5_4.service.UserService">
    	        <!--注入userDaodao对象
    	            name:属性值:类里面属性名称
    	            ref属性:创建的userDao对象bean标签的属性值,通过id值,把dao对象注入到userService对象中
    	        -->
    	        <property name="userDao" ref="userDaoImpl"></property>
    	    </bean>
    	</beans>
    
    在这里插入图片描述
  • 3.代码目录:
    在这里插入图片描述

b.注入内部bean:

b1.特点:

property标签内部使用嵌套的bean标签,这就是内部bean

b2.案例1:
  • 1.创建UserDao接口
    在这里插入图片描述

  • 2.创建Dao接口的实现类:
    在这里插入图片描述

  • 3.创建UserService类:
    在这里插入图片描述

  • 4.配置实现:
    在这里插入图片描述

  • 5.测试:
    在这里插入图片描述

b2.案例2:
  • 1.一对多关系:部门和员工;一个部门有多个员工,一个员工属于一个部门 ,部门是一,员工是多
  • 2.在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示

定义实体类:

在这里插入图片描述
在这里插入图片描述

实现内部bean配置:

在这里插入图片描述

测试:

在这里插入图片描述


c.注入简单类型

c1.特点:
  • 1.简单类型就是指的基本数据类型、包装类、String类型、枚举等
c2.注入简单类型举例1:
  • 1.定义实体类:
    在这里插入图片描述

  • 2.在set-di.xml配置文件配置:
    在这里插入图片描述

  • 3.单元测试:
    在这里插入图片描述

c3.在Spring中哪些属于是简单类型:
  • 1.面试会考简单类型都有哪些,我们通过Spring的源码来分析BeanUtils类发现简单类型包括“
    • 基本数据类型
    • 基本数据类型对应的包装类
    • String或其他的CharSequence子类
    • Number子类
    • Date子类
    • Enum子类
    • URI
    • URL
    • Temporal子类
    • Locale
    • Class
    • 另外还包括以上简单值类型对应的数组类型
      在这里插入图片描述
  • 2.对于8种包装类: java中的数据类型int,double等不是对象,无法通过向上转型获取到Object提供的方法,而像String却可以,只因为String是一个对象而不是一个类型。基本数据类型由于这样的特性,导致无法参与转型,泛型,反射等过程。为了弥补这个缺陷,java提供了包装类。
    在这里插入图片描述
c4.测试各个简单类型:
  • 1.定义实体类:
    在这里插入图片描述
  • 2.配置文件配置:
    在这里插入图片描述
  • 3.测试:
    在这里插入图片描述
  • 4.日期类型说明:
    在这里插入图片描述
c5.简单类型注入的经典应用:给数据源的属性注入值:
  • 1.假设我们现在要自己手写一个数据源,我们都知道所有的数据源都要实现javax.sql.DataSource接口,并且数据源中应该有连接数据库的信息,例如:driver、url、username、password等。
  • 2.什么是数据源??数据源就是能够提供Connection对象的,都是数据源
  • 1.编写类并实现DataSource接口 :
package com.powernode.spring6.beans;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;


public class MyDataSource implements DataSource {
    private String driver;
    private String url;
    private String username;
    private String 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 String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", 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;
    }
}

  • 2.编写配置文件:我们给driver、url、username、password四个属性分别提供了setter方法,我们可以使用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="dataSource" class="com.powernode.spring6.beans.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>
  
</beans>
  • 3.测试程序:
@Test
public void testDataSource(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-datasource.xml");
    MyDataSource dataSource = applicationContext.getBean("dataSource", MyDataSource.class);
    System.out.println(dataSource);
}

d.级联赋值

d1.案例1:
  • 1.定义Clazz类:
package com.jianqun.beans;
public class Clazz {
    private String name;

    public Clazz() {
    }

    public Clazz(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Clazz{" +
                "name='" + name + '\'' +
                '}';
    }
}

  • 2.定义Student类:
package com.jianqun.beans;
public class Student {
    private String name;
    private Clazz clazz;

    public Student() {
    }

    public Student(String name, Clazz clazz) {
        this.name = name;
        this.clazz = clazz;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }


    public Clazz getClazz() {
        return clazz;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", clazz=" + clazz +
                '}';
    }
}

  • 3.定义配置文件:spring-cascade.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="clazzBean" class="com.jianqun.beans.Clazz"/> </bean>

    <bean id="studentBean" class="com.jianqun.beans.Student">
        <property name="name" value="张三"/>

        <!--要点1:以下两行配置的顺序不能颠倒,先把班级对象注入过来,拿到班级对象后,再操作这个对象中的属性名-->
        <property name="clazz" ref="clazzBean"/>
        <!--要点2:clazz属性必须有getter方法-->
        <property name="clazz.name" value="高三一班"/>
    </bean>
</beans>
  • 4.定义程序:
@Test
public void testCascade(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-cascade.xml");
    Student student = applicationContext.getBean("studentBean", Student.class);
    System.out.println(student);
}

要点:
在spring配置文件中,如上,注意顺序
在spring配置文件中,clazz属性必须提供getter方法

d2.案例2:
  • 1.定义部门类:
    在这里插入图片描述

  • 2.定义员工类:
    在这里插入图片描述

  • 3.级联赋值:

外部bean赋值:

在这里插入图片描述

级联赋值:

在这里插入图片描述

  • 4.测试:
    在这里插入图片描述

e.注入数组

e1.当数组中的元素是简单类型:
  • 1.定义Person类:
package com.jianqun.beans;
import java.util.Arrays;
public class Person {
    private String[] favariteFoods;
    public void setFavariteFoods(String[] favariteFoods) {
        this.favariteFoods = favariteFoods;
    }

    @Override
    public String toString() {
        return "Person{" +
                "favariteFoods=" + Arrays.toString(favariteFoods) +
                '}';
    }
}

  • 2.编写配置文件:spring-array-simple.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="person" class="com.jianqun.beans.Person">
        <property name="favariteFoods">
            <array>
                <value>鸡排</value>
                <value>汉堡</value>
                <value>鹅肝</value>
            </array>
        </property>
    </bean>
</beans>
  • 3.测试代码:
@Test
public void testArraySimple(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-array-simple.xml");
    Person person = applicationContext.getBean("person", Person.class);
    System.out.println(person);
}
e2.当数组中的元素是非简单类型:一个订单中包含多个商品。
  • 1.定义实体类:
package com.jianqun.beans;

public class Goods {
    private String name;

    public Goods() {
    }

    public Goods(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • 2.订单类:
package com.jianqun.beans;
import java.util.Arrays;
public class Order {
    // 一个订单中有多个商品
    private Goods[] goods;
    public Order() {
    }
    public Order(Goods[] goods) {
        this.goods = goods;
    }
    public void setGoods(Goods[] goods) {
        this.goods = goods;
    }
    @Override
    public String toString() {
        return "Order{" +
                "goods=" + Arrays.toString(goods) +
                '}';
    }
}
  • 3.配置文件:spring-array.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="goods1" class="com.jianqun.beans.Goods">
        <property name="name" value="西瓜"/>
    </bean>

    <bean id="goods2" class="com.jianqun.beans.Goods">
        <property name="name" value="苹果"/>
    </bean>

    <bean id="order" class="com.jianqun.beans.Order">
        <property name="goods">
            <array>
                <!--这里使用ref标签即可-->
                <ref bean="goods1"/>
                <ref bean="goods2"/>
            </array>
        </property>
    </bean>

</beans>
  • 4.测试代码:
@Test
public void testArray(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-array.xml");
    Order order = applicationContext.getBean("order", Order.class);
    System.out.println(order);
}

总结:要点:
如果数组中是简单类型,使用value标签
如果数组中是非简单类型,使用ref标签


f.注入List集合

f1.编码实现:List集合是有序可重复的:
package com.jiaqun.beans;

import java.util.List;

public class People {
    // 一个人有多个名字
    private List<String> names;

    public void setNames(List<String> names) {
        this.names = names;
    }

    @Override
    public String toString() {
        return "People{" +
                "names=" + names +
                '}';
    }
}

  • 2.配置文件:spring-collection.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="peopleBean" class="com.jianqun.beans.People">
        <property name="names">
            <list>
                <value>铁锤</value>
                <value>张三</value>
                <value>张三</value>
                <value>张三</value>
                <value></value>
            </list>
        </property>
    </bean>
</beans>
  • 3.测试程序:
@Test
public void testCollection(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-collection.xml");
    People peopleBean = applicationContext.getBean("peopleBean", People.class);
    System.out.println(peopleBean);
}

注意:注入List集合的时候使用list标签,如果List集合中是简单类型使用value标签,反之使用ref标签。

g.注入Set集合:

g1.Set集合:

Set集合是无序不可重复的

  • 1.定义实体类:
package com.jiaqun.beans;

import java.util.List;
import java.util.Set;

public class People {
    // 一个人有多个电话
    private Set<String> phones;

    public void setPhones(Set<String> phones) {
        this.phones = phones;
    }
    
    //......
    
    @Override
    public String toString() {
        return "People{" +
                "phones=" + phones +
                ", names=" + names +
                '}';
    }
}

  • 2.定义配置类:
<?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="peopleBean" class="com.jianqun.beans.People">
        <property name="phones">
            <set>
                <!--非简单类型可以使用ref,简单类型使用value-->
                <value>110</value>
                <value>110</value>
                <value>120</value>
                <value>120</value>
                <value>119</value>
                <value>119</value>
            </set>
        </property>
    </bean>
</beans>

要点:
使用<set>标签
set集合中元素是简单类型的使用value标签,反之使用ref标签

  • 3.测试:
    在这里插入图片描述

h.注入Map集合

h1.定义实体类:
package com.powernode.spring6.beans;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class People {
    // 一个人有多个住址
    private Map<Integer, String> addrs;

    public void setAddrs(Map<Integer, String> addrs) {
        this.addrs = addrs;
    }
    
    //......
    
    @Override
    public String toString() {
        return "People{" +
                "addrs=" + addrs +
                ", phones=" + phones +
                ", names=" + names +
                '}';
    }

}

  • 2.编写配置文件:spring-collection.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="peopleBean" class="com.jianqun.beans.People">
        <property name="addrs">
            <map>
                <!--如果key不是简单类型,使用 key-ref 属性-->
                <!--如果value不是简单类型,使用 value-ref 属性-->
                <entry key="1" value="北京大兴区"/>
                <entry key="2" value="上海浦东区"/>
                <entry key="3" value="深圳宝安区"/>
            </map>
        </property>
    </bean>
</beans>

要点:使用标签
如果key是简单类型,使用 key 属性反之使用 key-ref 属性
如果value是简单类型,使用 value 属性,反之使用 value-ref 属性

h2.注入数组 + 注入List集合 + 注入Set集合 + 注入Map集合(基本数据类型)
  • 1.创建类,在类中定义数组,集合类型的属性
package com.jianqun.spring5.collectiontype;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * @author jianqun
 * @email:1033586391@qq.com
 * @creat 2022-02-06-14:07
 */
public class Stu {
    //数组类型属性
    private String[] courses;
    public void setCourses(String[] courses) {
        this.courses = courses;
    }

    //list集合类型
    private  List<String> list;

    public void setList(List<String> list) {
        this.list = list;
    }
    
    //set集合类型
    private Set<String> sets;
    public void setSets(Set<String> sets) {
        this.sets = sets;
    }

    //Map集合类型
    private Map<String,String> maps;
    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }
}
  • 2.在spring的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">

    <!--集合类型的属性注入-->
    <bean id="stu" class="com.jianqun.spring5.collectiontype.Stu">
        <!-- 数组类型的属性注入-->
        <property name="courses">
            <array>
                <value>PHP</value>
                <value>Database</value>
            </array>
        </property>

        <!-- list集合类型的属性注入-->
        <property name="list">
            <list>
                <value>PHP</value>
                <value>Database</value>
            </list>
        </property>

        <!-- set类型的属性注入-->
        <property name="sets">
            <set>
                <value>Mysql</value>
                <value>Redis</value>
            </set>
        </property>

        <!-- map类型的属性注入-->
        <property name="maps">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>
    </bean>
</beans>
  • 3.测试输出结果
package com.jianqun.spring5.test;

import com.jianqun.spring5.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author jianqun
 * @email:1033586391@qq.com
 * @creat 2022-02-06-14:28
 */
public class TestSpring {
    @Test
    public void test1(){
        //解析xml文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //反射得到类对象
        Stu stu = context.getBean("stu", Stu.class);
        //对象调方法
        stu.test();
    }
}
  • 4.输出结果
    在这里插入图片描述
h3.注入数组 + 注入List集合 + 注入Set集合 + 注入Map集合(对象类型值)
  • 1.定义类:
// 课程类
package com.jianqun.spring5.collectiontype;

/**
 * @author jianqun
 * @email:1033586391@qq.com
 * @creat 2022-02-06-15:16
 */

//课程类
public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }
}
//学生类
package com.jianqun.spring5.collectiontype;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author jianqun
 * @email:1033586391@qq.com
 * @creat 2022-02-06-14:07
 */
public class Stu {
    //学生所学的多门课程,存放的不再是字符串类型,而是课程类型
    private List<Course> courseslists;
    public void setCourseslists(List<Course> courseslists) {
        this.courseslists = courseslists;
    }

    public void test(){

    }
}
//配置文件
<?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="stu" class="com.jianqun.spring5.collectiontype.Stu">

        <!-- 注入list集合类型的 值是个对象 -->
        <property name="courseslists">
            <list>
                <ref bean="courses1"></ref>
                <ref bean="courses2"></ref>
            </list>
        </property>

    </bean>

    <!-- 定义多个course对象-->
    <bean id="courses1" class="com.jianqun.spring5.collectiontype.Course">
        <property name="cname" value="JAVA1111"></property>
    </bean>
    <bean id="courses2" class="com.jianqun.spring5.collectiontype.Course">
        <property name="cname" value="JAVA222"></property>
    </bean>
</beans>
package com.jianqun.spring5.test;

import com.jianqun.spring5.collectiontype.Course;
import com.jianqun.spring5.collectiontype.Stu;
import com.jianqun.spring5.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author jianqun
 * @email:1033586391@qq.com
 * @creat 2022-02-06-14:28
 */
 // 编码测试
public class TestSpring {
   @Test
    public void test2(){
        //解析xml文件
        ClassPathXmlApplicationContext context2 = new ClassPathXmlApplicationContext("bean1.xml");
        //反射得到类对象
        Stu stu = context2.getBean("stu", Stu.class);
        //对象调方法
        System.out.println(stu);
    }
  }

把集合注入部分提取出来,作为公共部分,避免仅仅在一个类中可用

  • 1.定义Book类
package com.jianqun.spring5.collectiontype;

import java.util.List;

/**
 * @author jianqun
 * @email:1033586391@qq.com
 * @creat 2022-02-06-15:36
 */
public class Book {
    private List<String> list;
    public void setList(List<String> list) {
        this.list = list;
    }
    public void test(){
        System.out.println("list:" + list);
    }
}
  • 2.引入util名称空间
<?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">

</beans>
  • 3.使用util标签完成list集合 的注入提取
<?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:list id="booklist">
           <value>java</value>
           <value>php</value>
           <value>sql</value>
        </util:list>

        <!-- 提取list集合的类型   -->
        <bean id="book" class="com.jianqun.spring5.collectiontype.Book">
            <property name="list" ref="booklist"></property>
        </bean>
</beans>
  • 4.测试
package com.jianqun.spring5.test;
import com.jianqun.spring5.collectiontype.Book;
import com.jianqun.spring5.collectiontype.Course;
import com.jianqun.spring5.collectiontype.Stu;
import com.jianqun.spring5.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author jianqun
 * @email:1033586391@qq.com
 * @creat 2022-02-06-14:28
 */
public class TestSpring {
	 @Test
    public void test3(){
        //解析xml文件
        ClassPathXmlApplicationContext context2 = new ClassPathXmlApplicationContext("bean2.xml");
        //反射得到类对象
        Book book = context2.getBean("book", Book.class);
        //对象调方法
        book.test();
    }
  • 输出结果
    在这里插入图片描述

J.注入Properties

J1.特点:
  • 1.java.util.Properties继承java.util.Hashtable,所以Properties也是一个Map集合
J2.编码实现:
  • 1.定义类:
package com.jianqun.beans;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class People {

    private Properties properties;

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    
    //......

    @Override
    public String toString() {
        return "People{" +
                "properties=" + properties +
                ", addrs=" + addrs +
                ", phones=" + phones +
                ", names=" + names +
                '}';
    }
}

  • 2.配置文件编写:
<?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="peopleBean" class="com.powernode.spring6.beans.People">
        <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>
            </props>
        </property>
    </bean>
</beans>

要点: 使用<props>标签嵌套<prop>标签完成

  • 3.测试:
    在这里插入图片描述

K.注入null和空字符串

K1.特点:
  • 1.注入空字符串使用:<value/> 或者 value=""
  • 2.注入null使用:<null/> 或者 不为该属性赋值
K2.注入空字符串:
  • 1.定义实体类:vip
package com.jianqun.beans;
public class Vip {
    private String email;

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Vip{" +
                "email='" + email + '\'' +
                '}';
    }
}

  • 2.配置文件编写:spring-null.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="vipBean" class="com.jianqun.beans.Vip">
        <!--空串的第一种方式-->
        <!--<property name="email" value=""/>-->
        <!--空串的第二种方式-->
        <property name="email">
            <value/>
        </property>
    </bean>

</beans>
  • 3.测试:
@Test
public void testNull(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-null.xml");
    Vip vipBean = applicationContext.getBean("vipBean", Vip.class);
    System.out.println(vipBean);
}
K3.怎么注入null:
  • 1.配置文件spring-null.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="vipBean" class="com.jianqun.beans.Vip" />

</beans>
  • 2.第二种方式:使用<null/>
<?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="vipBean" class="com.powernode.spring6.beans.Vip">
        <property name="email">
            <null/>
        </property>
    </bean>

</beans>

L.注入的值中含有特殊符号:

L1.特殊符号问题:
  • 1.XML中有5个特殊字符,分别是:<、>、'、"、&,以上5个特殊符号在XML中会被特殊对待,会被当做XML语法的一部分进行解析,如果这些特殊符号直接出现在注入的字符串当中,会报错
    在这里插入图片描述
L2.解决方案包括两种:
  • 1.第一种:特殊符号使用转义字符代替。
  • 2.第二种:将含有特殊符号的字符串放到:<![CDATA[]]> 当中。因为放在CDATA区中的数据不会被XML文件解析器解析。
  • 3.5个特殊字符对应的转义字符分别是
    • 特殊字符:> | 转义字符:&gt
    • 特殊字符:< | 转义字符:&lt
    • 特殊字符:’ | 转义字符:&apos
    • 特殊字符:" | 转义字符:&quot
    • 特殊字符:& | 转义字符:&amp
L3.编码实现:先使用转义字符来代替:
package com.jianqun.beans;
public class Math {
    private String result;

    public void setResult(String result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "Math{" +
                "result='" + result + '\'' +
                '}';
    }
}

  • 2.配置文件:spring-special.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="mathBean" class="com.powernode.spring6.beans.Math">
        <property name="result" value="2 &lt; 3"/>
    </bean>
</beans>
  • 3.测试程序:
@Test
public void testSpecial(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-special.xml");
    Math mathBean = applicationContext.getBean("mathBean", Math.class);
    System.out.println(mathBean);
}
L4.CDATA方式实现特殊符号赋值:
  • 1.配置文件:spring-special.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="mathBean" class="com.powernode.spring6.beans.Math">
        <property name="result">
            <!--只能使用value标签-->
            <value><![CDATA[2 < 3]]></value>
        </property>
    </bean>

</beans>

注意:使用CDATA时,不能使用value属性,只能使用value标签。


1.4.P命名空间注入

a.p命名空间注入的目的:

  • 1.是为了简化配置
  • 2.使用p命名空间注入的前提条件包括两个:
    • 第一:在XML头部信息中添加p命名空间的配置信息:xmlns:p="http://www.springframework.org/schema/p"
    • 第二:p命名空间注入是基于setter方法的,所以需要对应的属性提供setter方法

b.编码实现:

  • 1.定义类:
package com.jianqun.beans;
public class Customer {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  • 3.配置文件:spring-p.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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="customerBean" class="com.powernode.spring6.beans.Customer" p:name="zhangsan" p:age="20"/>

</beans>

在这里插入图片描述

  • 4.测试程序:
    在这里插入图片描述
  • 5.把实体类中的set方法去掉来验证P命名空间方式是否依赖Set方法:
    在这里插入图片描述

p命名空间实际上是对set注入的简化


1.5.util命名空间

a.util命名空间作用:

  • 1.使用util命名空间可以让配置复用
  • 2.使用util命名空间的前提是:在spring配置文件头部添加配置信息。如下:
    在这里插入图片描述

b.编码实现:

package com.powernode.spring6.beans;

import java.util.Properties;

public class MyDataSource1 {
    private Properties properties;

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "MyDataSource1{" +
                "properties=" + properties +
                '}';
    }
}

package com.powernode.spring6.beans;

import java.util.Properties;

public class MyDataSource2 {
    private Properties properties;

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "MyDataSource2{" +
                "properties=" + properties +
                '}';
    }
}

  • 3.配置文件:spring-util.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"
       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="prop">
        <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>

    <bean id="dataSource1" class="com.powernode.spring6.beans.MyDataSource1">
        <property name="properties" ref="prop"/>
    </bean>

    <bean id="dataSource2" class="com.powernode.spring6.beans.MyDataSource2">
        <property name="properties" ref="prop"/>
    </bean>
</beans>

1.6.基于XML的自动装配:

  • 1.Spring还可以完成自动化的注入,自动化注入又被称为自动装配。它可以根据名字进行自动装配,也可以根据类型进行自动装配

a.根据名称自动装配:

a1.编码实现:
  • 1.UserDao
package com.jianqun.dao;


public class UserDao {

    public void insert(){
        System.out.println("正在保存用户数据。");
    }
}
  • 2.UserService
package com.powernode.spring6.service;
import com.powernode.spring6.dao.UserDao;
public class UserService {
    private UserDao aaa;
    // 这个set方法非常关键
    public void setAaa(UserDao aaa) {
        this.aaa = aaa;
    }

    public void save(){
        aaa.insert();
    }
}

  • 3.Spring的配置文件这样配置:spring-autowire.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="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/>
    
	<!-- id一般也叫做是bean的名称,根据名称匹配的话,就和实体类中的set方法一样,把set去掉,然后第一个字母变小写-->
    <bean id="aaa" class="com.powernode.spring6.dao.UserDao"/>

</beans>

这个配置起到关键作用:

  • UserService Bean中需要添加autowire="byName",表示通过名称进行装配
  • UserService类中有一个UserDao属性,而UserDao属性的名字是aaa,对应的set方法是setAaa(),正好和UserDao Bean的id是一样的。这就是根据名称自动装配
  • 4.测试:
@Test
public void testAutowireByName(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
    UserService userService = applicationContext.getBean("userService", UserService.class);
    userService.save();
}
a2.测试一下byName装配是和属性名有关还是和set方法名有关系:
package com.powernode.spring6.service;

import com.powernode.spring6.dao.UserDao;

public class UserService {
    // 这里没修改
    private UserDao aaa;

    /*public void setAaa(UserDao aaa) {
        this.aaa = aaa;
    }*/

    // set方法名变化了
    public void setDao(UserDao aaa){
        this.aaa = aaa;
    }

    public void save(){
        aaa.insert();
    }
}

  • 2.在执行测试程序:
    在这里插入图片描述
  • 3.通过测试得知,aaa属性并没有赋值成功。也就是并没有装配成功。我们将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="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/>
  <!--这个id修改了-->
  <bean id="dao" class="com.powernode.spring6.dao.UserDao"/>
  
</beans>
  • 4.执行测试程序:
    在这里插入图片描述

这说明,如果根据名称装配(byName),底层会调用set方法进行注入。例如:setAge() 对应的名字是age,setPassword()对应的名字是password,setEmail()对应的名字是email。


b.根据类型自动装配:

b1.编码实现:
  • 1.定义AccountDao:
package com.powernode.spring6.dao;

public class AccountDao {
    public void insert(){
        System.out.println("正在保存账户信息");
    }
}
  • 1.定义service:
package com.powernode.spring6.service;

import com.powernode.spring6.dao.AccountDao;

public class AccountService {
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public void save(){
        accountDao.insert();
    }
}

  • 3.配置文件:
<?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">

    <!--byType表示根据类型自动装配-->
    <bean id="accountService" class="com.powernode.spring6.service.AccountService" autowire="byType"/>

    <bean class="com.powernode.spring6.dao.AccountDao"/>

</beans>
  • 4.测试程序:
@Test
public void testAutowireByType(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-autowire.xml");
    AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
    accountService.save();
}
b2.我们把UserService中的set方法注释掉,再执行:
  • 1.可以看到无论是byName还是byType,在装配的时候都是基于set方法的。所以set方法是必须要提供的。提供构造方法是不行的,
  • 2.如果byType,根据类型装配时,如果配置文件中有两个类型一样的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">

    <bean id="accountService" class="com.powernode.spring6.service.AccountService" autowire="byType"/>

    <bean id="x" class="com.powernode.spring6.dao.AccountDao"/>
    <bean id="y" class="com.powernode.spring6.dao.AccountDao"/>

</beans>

当byType进行自动装配的时候,配置文件中某种类型的Bean必须是唯一的,不能出现多个


2.构造注入方式实心依赖注入:

  • 1.set注入是对象产生之后,再去给属性赋值 的时候注入的
  • 2.构造注入就是通过构造方法给属性赋值,它是在对象实例化的时候进行注入的

2.1.编码实现:

  • 1.OrderDao.java
package com.jianqun.spring6.dao;
public class OrderDao {
    public void deleteById(){
        System.out.println("正在删除订单。。。");
    }
}
  • 2.OrderService.java
package com.jianqun.service;
import com.jianqun.dao.OrderDao;
public class OrderService {
    private OrderDao orderDao;

    // 通过反射机制调用构造方法给属性赋值
    public OrderService(OrderDao orderDao) {
        this.orderDao = orderDao;
    }

    public void delete(){
        orderDao.deleteById();
    }
}
  • 3.Spring.xml
<bean id="orderDaoBean" class="com.jianqun.dao.OrderDao"/>

<bean id="orderServiceBean" class="com.jianqun.service.OrderService">
  <!--index="0"表示构造方法的第一个参数,将orderDaoBean对象传递给构造方法的第一个参数。-->
  <constructor-arg index="0" ref="orderDaoBean"/>
  
</bean>
  • 4.测试程序:
@Test
public void testConstructorDI(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);
    orderServiceBean.delete();
}
  • 5.运行结果:
    在这里插入图片描述

2.2.如果构造方法有两个参数:

  • 1.OrderService.java
package com.jianqun.service;

import com.jianqun.dao.OrderDao;
import com.jianqun.dao.UserDao;

public class OrderService {
    private OrderDao orderDao;
    private UserDao userDao;

    // 通过反射机制调用构造方法给属性赋值
    public OrderService(OrderDao orderDao, UserDao userDao) {
        this.orderDao = orderDao;
        this.userDao = userDao;
    }

    public void delete(){
        orderDao.deleteById();
        userDao.insert();
    }
}
  • 2.spring配置文件:
<bean id="orderDaoBean" class="com.powernode.dao.OrderDao"/>

<bean id="orderServiceBean" class="com.powernode.service.OrderService">
  <!--第一个参数下标是0-->
  <constructor-arg index="0" ref="orderDaoBean"/>
  <!--第二个参数下标是1-->
  <constructor-arg index="1" ref="userDaoBean"/>
</bean>

<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
  • 3.执行测试程序:
    在这里插入图片描述

2.3.c命名空间注入

a.概述:

  • 1.对于c命名空间是简化构造方法注入的。使用c命名空间的两个前提条件:
    • 第一:需要在xml配置文件头部添加信息:xmlns:c="http://www.springframework.org/schema/c
    • 第二:需要提供构造方法

b.代码测试:

  • 1.定义实体类:
package com.powernode.spring6.beans;

public class MyTime {
    private int year;
    private int month;
    private int day;

    public MyTime(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    @Override
    public String toString() {
        return "MyTime{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }
}

  • 2.配置文件:spring-c.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:c="http://www.springframework.org/schema/c"
       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="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:year="1970" c:month="1" c:day="1"/>-->

    <bean id="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:_0="2008" c:_1="8" c:_2="8"/>

</beans>
  • 3.测试程序:测试程序
    在这里插入图片描述
  • 4.把实体类中的构造方法注释掉来验证是否依赖构造方法实现的:
    在这里插入图片描述
  • c命名空间是依靠构造方法的
  • 注意:不管是p命名空间还是c命名空间,注入的时候都可以注入简单类型以及非简单类型

2.4.其他注意事项:

a.不使用参数下标,使用参数的名字也可以

<bean id="orderDaoBean" class="com.jianqun.dao.OrderDao"/>

<bean id="orderServiceBean" class="com.jianqun.service.OrderService">
  <!--这里使用了构造方法上参数的名字-->
  <constructor-arg name="orderDao" ref="orderDaoBean"/>
  <constructor-arg name="userDao" ref="userDaoBean"/>
</bean>

<bean id="userDaoBean" class="com.jianqun.spring6.dao.UserDao"/>

b.不指定参数下标,不指定参数名字,也可以

<bean id="orderDaoBean" class="com.jianqun.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.jianqun.service.OrderService">
  <!--没有指定下标,也没有指定参数名字-->
  <constructor-arg ref="orderDaoBean"/>
  <constructor-arg ref="userDaoBean"/>
</bean>

<bean id="userDaoBean" class="com.jianqun.dao.UserDao"/>

在这里插入图片描述

c.配置文件中构造方法参数的类型顺序和构造方法参数的类型顺序不一致无影响

<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>

<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService">
  <!--顺序已经和构造方法的参数顺序不同了-->
  <constructor-arg ref="userDaoBean"/>
  <constructor-arg ref="orderDaoBean"/>
</bean>

<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>

2.5.总结:

  • 通过测试得知,通过构造方法注入的时候
    • 可以通过下标
    • 可以通过参数名
    • 也可以不指定下标和参数名,可以类型自动推断
  • Spring在装配方面做的还是比较健壮的

3.Spring引入外部属性配置文件

3.1.概述:

  • 1.我们都知道编写数据源的时候是需要连接数据库的信息的,例如:driver url username password等信息。这些信息可以单独写到一个属性配置文件中吗,这样用户修改起来会更加的方便。当然可以

3.2.编码实现:

  • 1.第一步:写一个数据源类,提供相关属性。
package com.powernode.spring6.beans;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

public class MyDataSource implements DataSource {
    @Override
    public String toString() {
        return "MyDataSource{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    private String driver;
    private String url;
    private String username;
    private String 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;
    }

    //......
}

  • 2.第二步:在类路径下新建jdbc.properties文件,并配置信息
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=root123

在这里插入图片描述

  • 3.第三步:在spring配置文件中引入context命名空间。
<?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">

</beans>
  • 4.第四步:在spring中配置使用jdbc.properties文件
    在这里插入图片描述
<?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="dataSource" class="com.powernode.spring6.beans.MyDataSource">
        <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>
</beans>
  • 5.测试程序:
@Test
public void testProperties(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-properties.xml");
    MyDataSource dataSource = applicationContext.getBean("dataSource", MyDataSource.class);
    System.out.println(dataSource);
}
  • 6.执行结果:
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值