【Spring6详解之IoC的实现】

一、控制反转

1.控制反转是一种思想。
2.控制反转的目的:降低程序的耦合度,从而提高程序的扩展力,达到OCP原则和DIP原则。
3.什么是控制反转?
(1)将创建对象这一任务交给容器去完成;
(2)对象和对象之间的关系交给容器去管理。
4.真正实现控制反转这个思想的技术是依赖注入DI
(Dependence Injection )

二、依赖注入

1.依赖注入实现了控制反转的思想。
2.Spring通过依赖注入的方式来完成Bean的管理
管理指:Bean对象的创建,以及Bean对象之间的关系的维护。
3.依赖注入:
(1)依赖指的是对象和对象之间的关联关系。
(2)注入指的是一种数据传递行为,通过注入行为来让对象和对象产生关系。
4.依赖注入的常见两种方式:
(1)set注入
(2)构造注入

三、set 注入

(1)set注入是基于set方法实现的
因为反射机制要调用这个方法给属性赋值。

<?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.dao.UserDao"/>

    <bean id="userServiceBean" class="com.powernode.spring6.service.UserService">
        <property name="userDao" ref="userDaoBean"/>
    </bean>

</beans>

*通过property标签获取属性名:userDao
*通过属性名推断出set方法:setUserDao
*通过反射机制调用setUserDao( )方法给属性赋值
*在property标签里,name是属性名,ref注入对象的id,将对象之间关联起来

(2)注入外部Bean(如上)
特点:在property标签中使用ref属性进行注入
(3)注入内部Bean
特点:在bean标签中嵌套bean标签

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="userServiceBean" class="com.service.UserService">
        <property name="userDao">
            <bean class="com.dao.UserDao"/>
        </property>
    </bean>
</beans>

(4)注入简单类型

<?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">
    <!--如果像这种int类型的属性,我们称为简单类型,简单类型在注入的时候要使用value属性或者value标签,不能使用ref-->
    <!--value标签赋值-->
    <bean id="userBean1" class="com.beans.User">
        <property name="age">
            <value>20</value>
        </property>
    </bean>
    <!--value属性-->
    <bean id="userBean2" class="com.beans.User">
    	<property name="age" value="22"></property>
    </bean>
</beans>

简单类型包括:
*基本简单类型
*基本简单类型对应的包装类
*String或其他的CharSequence子类
*Number子类
*Date子类
*Enum子类
*URL
*URI
*Temporal子类
*Locale
Class
*还包括以上简单类型对应的数组类型

测试如下:

package com.beans;

import java.net.URI;
import java.net.URL;
import java.time.LocalDate;
import java.util.Date;
import java.util.Locale;

public class A {
	//基本数据类型
    private byte b;
    private short s;
    private int i;
    private long l;
    private float f;
    private double d;
    private boolean flag;
    private char c;
	//包装类
    private Byte b1;
    private Short s1;
    private Integer i1;
    private Long l1;
    private Float f1;
    private Double d1;
    private Boolean flag1;
    private Character c1;
	//String类
    private String str;
	//日期类
    private Date date;
	//枚举类
    private Season season;
	//URI
    private URI uri;
	//URL
    private URL url;
	//时区
    private LocalDate localDate;
    
    private Locale locale;
	//Class类
    private Class clazz;
    
    // 生成setter方法,略
    // 生成toString方法,略
}

enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}
<?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="a" class="com.beans.A">
        <property name="b" value="1"/>
        <property name="s" value="1"/>
        <property name="i" value="1"/>
        <property name="l" value="1"/>
        <property name="f" value="1"/>
        <property name="d" value="1"/>
        <property name="flag" value="false"/>

        <property name="c" value="a"/>
        <property name="b1" value="2"/>
        <property name="s1" value="2"/>
        <property name="i1" value="2"/>
        <property name="l1" value="2"/>
        <property name="f1" value="2"/>
        <property name="d1" value="2"/>
        <property name="flag1" value="true"/>
        <property name="c1" value="a"/>

        <property name="str" value="zhangsan"/>
        <!--注意:value后面的日期字符串格式不能随便写,必须是Date对象toString()方法执行的结果。-->
        <property name="date" value="Fri Sep 30 15:26:38 CST 2022"/>
        <property name="season" value="WINTER"/>
        <property name="uri" value="/save.do"/>
        <!--spring6之后,会自动检查url是否有效,如果无效会报错。-->
        <property name="url" value="http://www.baidu.com"/>
        <property name="localDate" value="EPOCH"/>
        <!--java.util.Locale 主要在软件的本地化时使用。它本身没有什么功能,更多的是作为一个参数辅助其他方法完成输出的本地化。-->
        <property name="locale" value="CHINESE"/>
        <property name="clazz" value="java.lang.String"/>
    </bean>
</beans>

(5)级联属性赋值

<?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="banjiBean" class="com.beans.banji"/>
    <bean id="student" class="com.beans.Student">
        <property name="name" value="张三"/>
        <!--要点1:以下两行配置的顺序不能颠倒-->
        <property name="banji" ref="banjiBean"/>
        <!--要点2:banji对象的name属性须有getter方法-->
        <property name="banji.name" value="高一二班"/>
    </bean>
</beans>

(6)注入数组

property标签里面是array标签
如果L数组集合中的值是简单类型使用value标签,反之用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">
    <bean id="person" class="com.beans.Goods">
        <property name="favariteFoods">
            <array>
                <value>鸡排</value>
                <value>汉堡</value>
                <value>鹅肝</value>
            </array>
        </property>
    </bean>
</beans>

数组中的元素是非简单类型:

<?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.beans.Goods">
        <property name="name" value="鸡排"/>
    </bean>
    <bean id="goods2" class="com.beans.Goods">
        <property name="name" value="汉堡"/>
    </bean>
        <bean id="goods3" class="com.beans.Goods">
        <property name="name" value="鹅肝"/>
    </bean>
    <bean id="order" class="com.beans.Order">
        <property name="goods">
            <array>
                <!--这里使用ref标签即可-->
                <ref bean="goods1"/>
                <ref bean="goods2"/>
                <ref bean="goods3"/>
            </array>
        </property>
    </bean>

</beans>

(7)注入List集合

*roperty标签里是list标签
*如果List集合中的值是简单类型使用value标签,反之用ref标签
*List集合:有序可重复

People.java

package com.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 +
                '}';
    }
}

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="peopleBean" class="com.beans.People">
        <property name="names">
            <list>
                <value>铁锤</value>
                <value>张三</value>
                <value>张三</value>
                <value>张三</value>
                <value>李四</value>
            </list>
        </property>
    </bean>
</beans>

输出结果为:铁锤、张三、张三、张三、李四

(8)注入Set集合

*poperty标签里使用set标签
*如果Set集合中的值是简单类型使用value标签,反之用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">
    <bean id="peopleBean" class="com.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>

输出结果为:110、120、119

(9)注入Map集合

*property标签里使用map标签
*如果key是简单类型使用key属性,反之用key-ref属性
*如果value是简单类型使用value属性,反之用value-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">
    <bean id="peopleBean" class="com.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>

(10)注入Properties标签

*java.util.Properties继承java.util.Hashtable,所以Properties也是一个Map集合
*property标签里面使用props标签,props标签里嵌套prop标签
*

package com.beans;
import java.util.Properties;

public class People {
    private Properties properties;
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    @Override
    public String toString() {
        return "People{" +
                "properties=" + 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="peopleBean" class="com.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>

(11)注入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="UserBean1" class="com.beans.User">
        <property name="email">
            <null/>
        </property>
    </bean>
	<!--方式二-->
	<bean id = "UserBean2" class = "com.beans.User">
		<property name = "email"></propery>
	</bean>
</beans>

(12)注入的值含有特殊符号

*在XML中有5个特殊的字符,分别是:< 、> 、’ 、" 、&
*以上字符会被当做XML语法的一部分进行解析,直接出现在注入的字符串中,会报错。
*解决方法:使用转义字符代替、将含有特殊符号的字符串放到<![CDATA[]]>中。

*5个特殊符号对应的转义字符是:

特殊字符转义字符
>&gt;
<&lt;
&apos;
"&quot;
&&amp;
<?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.beans.Math">
        <property name="result" value="2 &lt; 3"/>
    </bean>
</beans>

使用CDATA方式:

<?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.beans.Math">
        <property name="result">
            <!--只能使用value标签,不能使用value属性-->
            <value><![CDATA[2 < 3]]></value>
        </property>
    </bean>

</beans>

四、构造注入

*核心要点:通过构造方法给属性赋值
*通过构造方法注入时:
可以通过下标,
也可以通过参数、
也可以不指定下标和参数

<bean id="orderDaoBean" class="com.dao.OrderDao"/>
<!--使用参数下标-->
<bean id="orderServiceBean1" class="com.service.OrderService">  
<!--index="0"表示构造方法的第一个参数,将orderDaoBean对象传递给构造方法的第一个参数。-->
  <constructor-arg index="0" ref="orderDaoBean"/>
</bean>
<!--使用参数名-->
<bean id = "orderServiceBean2" class = "com.service.orderService">
	<constructor-arg name = "orderDao" ref = "orderDaoBean"/>
</bean>
<!--不使用下标,也不使用参数名-->
<bean id = "orderService3" class = "com.service.orderService">
	<constructor-arg ref = "orderDaoBean">
</bean>	

五、p命名空间注入

使用p命名空间注入的前提条件:
(1)在XML头部信息中添加p命名空间的配置信息:
xmlns:p=“http://www.springframework.org/schema/p”
(2)p命名空间注入是基于setter方法的,所以对应的属性提供setter方法。

<?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.beans.Customer" p:name="zhangsan" p:age="20"/>
</beans> 

六、c命名空间注入

使用c命名空间的两个前提条件:
(1)在XML头部信息中添加c命名空间的配置信息:
xmlns:p=“http://www.springframework.org/schema/c”
(2)c命名空间注入基于构造方法,所以要提供构造方法。

<?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="myTimeBean1" class="com.beans.MyTime" c:year="1970" c:month="1" c:day="1"/>
    <!--使用参数下标-->
    <bean id="myTimeBean2" class="com.beans.MyTime" c:_0="2008" c:_1="8" c:_2="8"/>
</beans>

七、使用util命名空间

使用util命名空间可以让配置复用
使用util的前提,在spring配置文件头部添加如下配置信息:
xmlns:util=“http://www.springframework.org/schema/util”
xsi:“http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd”

<?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.beans.MyDataSource1">
        <property name="properties" ref="prop"/>
    </bean>

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

八、基于XML的自动装配

(1)根据名称自动装配

<?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">
	<!--在userService中添加autowire="byName",表示通过名称进行装配-->
    <bean id="userService" class="com.service.UserService" autowire="byName"/>
    <!--在userService类中有一个UserDao属性,这个属性对应的名字为aaa,对应的set方法为setAaa(),在-->
    <bean id="aaa" class="com.powernode.spring6.dao.UserDao"/>

</beans>

(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="accountService" class="com.service.AccountService" autowire="byType"/>
    <bean id="x" class="com.dao.AccountDao"/>
</beans>

*无论是byName还是byType,都是基于set方法装配的,因此必须要提供set方法.
*在使用byType类型装配时,配置文件中某种类型的Bean是唯一的.

九、Spring 引入外部属性配置文件

以一个完整的程序为例:

(1) 第一步:写一个数据源类,提供相关属性

package com.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;

/**
 * @author 动力节点
 * @version 1.0
 * @className MyDataSource
 * @since 1.0
 **/
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文件,并配置信息。

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring
username=root
password=root123

(3) 第三步:在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.beans.MyDataSource">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </bean>
</beans>

(4) 测试:

@Test
public void testProperties(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-properties.xml");
    MyDataSource dataSource = applicationContext.getBean("dataSource", MyDataSource.class);
    System.out.println(dataSource);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值