IOC具体操作之Bean管理

什么是Bean管理?

Bean管理里面其实里面指的是两个操作。第一个就是由Spring给我们创建对象,就是通过bean标签,然后创建对象。第二个就是由Spring进行属性注入。比如一个Javabean中有一个private String userName属性,我们可以通过setter来设置属性。那么现在这个过程也可以交给Spring来做到。这个过程就叫做注入属性。

对象创建

在Spring的xml配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象的创建。

<bean id="sutdent" class="com.zxb.spring.bean.Student"></bean>

这样我们就创建了一个对象(通过无参构造创建)。

在bean标签中有很多属性,这里介绍常用的属性。

*id属性:唯一标识。表示给对象取一个标识或者说别名,然后通过标识或别名可以得到那个对象。

*class属性:类全路径(包类路径)

*name属性:name属性和id的作用是一样的,区别是id属性中不能加特殊符号,但是name中可以加一些特殊符号,比如/。现在基本没什么人用了,当初为struts1而生。

注意!创建对象的时候,默认也是执行无参数的构造方法完成对象的创建。框架中大都采用newInstance()的方式来创建对象,此方法调用的也是无参构造,所以都要把无参构造写上。如果写了有参没写无参就会报错。

属性注入

DI(Dependency Injection):依赖注入,就是注入属性。

第一种注入方式

使用set方法进行注入。需要在类中创建属性和对应的set方法

<bean id="book" class="com.zxb.spring.Book">
        <!--注入属性要写在bean标签里面,相当于对象调方法-->
        <!--
		   使用property完成属性注入
            name:类里面属性的名称
            value: 向属性注入的值
        -->
        <property name="bname" value="java从入门到放弃"></property>
        <property name="bauthor" value="头发护理秘籍"></property>
    </bean>

当使用ApplicationContext context = new ClassPathXmlApplicationContext(“xxx.xml”);来加载配置文件时,这一过程中,会帮我们完成对象创建,以及属性注入。

通过set注入,需要在bean标签内部写上property属性,较为麻烦。还有一种简化xml配置的操作,叫做p名称空间注入。此方式是简化set注入,而不是构造器注入的。

第一步:添加p名称空间在配置文件中。

xmlns:p="http://www.springframework.org/schema/p"

第二步:进行属性注入,在bean标签里面进行操作

<bean id="book" class="com.zxb.spring.bean.Book" p:bname="九阳神功" p:bauthor="无名氏"></bean>

这种通过p名称空间注入底层使用的还是set方法注入。只不过写法简化了。

第二种注入方式

使用有参构造进行属性注入
第一步:创建类,定义属性,创建属性对应的有参构造方法。
第二步:在Spring配置文件中进行配置。

<!--通过有参构造注入属性-->
    <bean id="orders" class="com.zxb.spring.bean.Orders">
        <constructor-arg name="oName" value="电脑"></constructor-arg>
        <constructor-arg name="address" value="China"></constructor-arg>
        <!--
        <constructor-arg index="0" value="电脑"></constructor-arg>
        <constructor-arg index="1" value="China"></constructor-arg>
        -->
    </bean>

通过index也是可以的,索引表示构造方法的第几个参数。但是一般用name,name更加准确。

注意!

一、

如果类中没有构造方法,只写了属性,在xml文件中,只能写上

<bean id="student1" class="com.zxb.spring.bean.Student"></bean>,这样会帮我们创建一个对象,属性都是默认值。如果这么定义bean标签,那么不能在bean标签内部写property,因为没有对应的setter。只有写了setter才能帮我们注入属性。

二、

如果类中写了属性,没写无参构造,但是有对应的有参构造方法,那么只写上

<bean id="student1" class="com.zxb.spring.bean.Student"></bean>会报错,这样写是找的无参构造,而我们没有写无参构造,我们要在bean标签中添加constructor-arg标签来给参数赋值。

总而言之,只写上<bean id="student1" class="com.zxb.spring.bean.Student"></bean>找的是无参构造,bean标签里面写属性了,那么找的就是对应的setter,如果没有就会报错。

注入其他类型属性

1、字面量

设置使用的固定值就叫做字面量。比如private String oName=“zs”; 这里zs就是字面量,固定死了。也可以通过property标签中的name和value设置固定值,这些固定值也叫做字面量。

​ (1)null值

<property name="address"  >
    <null></null>
    <null/>单标签双标签都可以
</property>

​ (2)属性值中包含特殊符号< >等

​ 方式一:使用& l t;或者& g t;

<!--属性值中包含特殊符号-->
<property name="address" value="&lt;杭州&gt;"></property>

方式二:CDATA域

注意 value可以当做标签写在property标签内部。

<property name="address">
    <value> <![CDATA[<杭州>]]> </value>
</property>

注入属性—外部bean

举个例子,比如操作中有三层,web层调用service层,service层调用dao层。现在先写两层,一个是service层,一个是dao层。通过service去调用dao,这个过程就叫做引入外部bean。

        //原始方式:创建UserDao对象
		//UserDao userDao = new UserDaoImpl();
		//userDao.update();

​ (1)创建两个类,service和dao类

​ (2)在service调用dao里面的方法

​ (3)在Spring配置文件中进行配置

java代码:

public class UserService {

    //创建UserDao类型属性,生成set方法
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void add() {
        System.out.println("service add...");
        userDao.update();
    }
}

xml配置:

<!--1 service和dao对象创建-->
    <bean id="userService" class="com.zxb.spring.service.UserService">
        <!--2 注入userDao对象
            name属性,类里面规范的属性的名字
            ref属性,创建userDao对象的bean的标签的id,表示我需要外部bean,ref就是外部bean的id。
        -->
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <bean id="userDaoImpl" class="com.zxb.spring.dao.UserDaoImpl"></bean>

**外部bean的注入,在当前类中需要使用到其他类时,我们只需要去创建一个外部类的变量名,随后创建该变量名的set方法。然后在xml中配置当前类和外部类也就是我们需要的其他类的bean标签。在当前类的bean标签中,使用property标签的ref属性,来注入外部bean。ref属性的值就是外部bean的id值。
**

注入属性–内部bean

(1)一对多关系:部门和员工

一个部门里面可以有多个员工,一个员工属于一个部门。

部门是一,员工是多。

(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类属性进行表示。

package com.zxb.spring.bean;

//员工类
public class Emp {
    private String eName;
    private String gender;
    //员工属于一个部门,使用对象形式表示
    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public void seteName(String eName) {
        this.eName = eName;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

package com.zxb.spring.bean;

//部门类
public class Dept {
    private String dName;

    public void setdName(String dName) {
        this.dName = dName;
    }
}

(3)在Spring配置文件中进行配置

<!--内部bean-->
    <bean id="emp" class="com.zxb.spring.bean.Emp">
        <!--先设置两个普通的属性-->
        <property name="eName" value="lucy"></property>
        <property name="gender" value=""></property>
        <!--设置对象类型属性 可以在外部建一个bean(对象),再通过ref引入
            但是这样是外部bean的写法,我们可以在property标签中嵌套一个bean
        -->
        <property name="dept">
            <bean id="dept" class="com.zxb.spring.bean.Dept">
                <property name="dName" value="安保部"></property>
            </bean>
        </property>
    </bean>

内部bean就是在property标签里面嵌套一个bean标签。

注入属性–级联赋值(通过外部bean)

还是使用员工和部门的例子,比如想实现向emp中赋值的时候,把dept中的dname也赋值。前面其实也做到了,现在是换一种写法来做级联赋值。你可以同时向你有关联的属性中设值。比如让部门中的属性都设值。就是向多个实体类中设值它的属性值。

写法一:

<!--级联赋值-->
    <bean id="emp" class="com.zxb.spring.bean.Emp">
        <!--先设置两个普通的属性-->
        <property name="eName" value="lucy"></property>
        <property name="gender" value=""></property>
        <!--级联赋值,第一种写法-->
        <property name="dept" ref="dept"></property>
    </bean>
    <bean id="dept" class="com.zxb.spring.bean.Dept">
        <property name="dName" value="财务部"></property>
    </bean>

写法2:

<!--级联赋值-->
    <bean id="emp" class="com.zxb.spring.bean.Emp">
        <!--先设置两个普通的属性-->
        <property name="eName" value="lucy"></property>
        <property name="gender" value=""></property>
        <property name="dept" ref="dept"></property>
        <!--级联赋值,第二种写法
            需要get方法获取属性(对象)
            因为都是私有的方法,set用来赋值,
            get用来获取,然后获取的是对象类型,然后通过对象.属性,
            再通过value进行赋值。
        -->
        <property name="dept.dName" value="安保部"></property>
    </bean>
    <bean id="dept" class="com.zxb.spring.bean.Dept"></bean>

注入属性–集合属性

1、注入数组类型属性

2、注入List结婚属性

3、注入Map集合类型

​ (1)、创建类,定义数组、list、map、set类型属性,并且生成它们的set方法。

package com.zxb.spring.collectiontype;

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

public class Stu {
    //1、数组类型属性
    private String[] courses;

    //2、list集合类型属性
    private List<String> list;

    //3、map集合类型属性
    private Map<String, String> map;

    //4、set集合类型属性
    private Set<String> set;

    public void setCourses(String[] courses) {
        this.courses = courses;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }
}

(2)在Spring配置文件中进行配置

数组类型注入因为有多个值,property标签的value属性只能赋一个值,所以需要

<property name="courses">
    <array>
    	<value></value>
        ...
    </array>
</property><property name="courses">
     <list>
        <value></value>
        ...
    </list>
</property>
<!--集合类型属性注入-->
    <bean id="stu" class="com.zxb.spring.collectiontype.Stu">
        <!--数组类型属性注入-->
        <property name="courses">
            <array>
                <value>java人</value>
                <value>java魂</value>
            </array>
        </property>
        <!--list类型属性注入-->
        <property name="list">
            <array>
                <value>张三</value>
                <value>小三</value>
            </array>
        </property>

        <!--map类型属性注入-->
        <property name="maps">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>

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

4、在集合里面设置对象类型值

​ 使用ref标签中的bean属性,bean里面写的是多个对象的id值。

​ 在xml中如下配置

		<property name="courseList"> <!-- 这个属性是List<Course>型的,注入的是Course类型 -->
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>

	    <!--在外部创建多个course对象-->
	    <bean id="course1" class="com.zxb.spring.collectiontype.Course">
	        <property name="cname" value="Spring框架"></property>
	    </bean>
	    <bean id="course2" class="com.zxb.spring.collectiontype.Course">
	        <property name="cname" value="MyBatis框架"></property>
	    </bean>

5、把集合注入部分提取出来,作为公共部分

​ (1)在Spring配置文件中引入名称空间util。

​ 第一步,在bean标签中添加

xmlns:util="http://www.springframework.org/schema/util"

​ 第二步,继续在bean标签中添加如下

http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd

​ 就是将beans修改成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:p="http://www.springframework.org/schema/p"
       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 https://www.springframework.org/schema/util/spring-util.xsd">

​ (2)使用util标签完成list集合属性抽取,使得其他bean也可以使用该属性。

<!-- 1、使用util提取list集合属性 -->
    <!--util可以抽取list、map、set等
        这个id相当于名字,相当于一个公共类里面取一个公共的名字
    -->
    <util:list id="bookList">
        <!--如果集合里面是基本数据类型,就用value标签
            如果集合里面是类类型,那么就用ref标签的bean属性
        -->
        <value>易筋经</value>
        <value>九阴真经</value>
        <value>九阳神功</value>
    </util:list>

    <!-- 2、将提取出来的属性注入对象 -->
    <bean id="book" class="com.zxb.spring5.collectiontype.Book">
        <!--使用ref标签将提取出来的属性注入,这样就将bookList中的值直接注入到属性中
            这样如果有多个bean,就可以通过ref来注入属性。
        -->
        <property name="list" ref="bookList"></property>
    </bean>

注入属性(xml自动装配)

​ 1、什么是自动装配?

​ 之前通过property标签的name和value属性手动设置哪个名称里面有什么值,这个值可以是普通数据类型,也可以是引用类型。通过value属性和ref属性指定你的属性值,这属于手动装配。

​ 那么自动装配就是不需要写property标签,根据你的属性类型或名称Spring会自动帮我们注入属性。根据指定装配规则(属性名称或者属性类型)。Spring自动将匹配的属性值注入。

​ 2、演示自动装配过程

​ 自动装配中主要由两种方式。一种是根据你的属性名称进行装配。另外一种是根据属性类型进行装配。

​ 在bean标签中有一个属性 autowire,通过它来配置自动装配
​ autowire属性有两个常用值:
​ byName 根据属性的名称进行注入,注入值的bean的id值要和类的属性名称一样,比如bean的id叫dept,而类里面属性名也叫dept,这样才能完成自动装配,否则就是null。应该说是和setXxx中set的属性一致。
​ byType根据属性类型注入,byType要注意,相同类型的bean不能定义多个,只能有一个,定义多个就会找不到注入哪一个,就会报错。

byName:

<bean id="emp" class="com.zxb.spring5.autowire.Emp" autowire="byName"></bean>	
<bean id="dept" class="com.zxb.spring5.autowire.Dept"></bean>

byType:

	<bean id="emp" class="com.zxb.spring5.autowire.Emp" autowire="byType"></bean>
    <bean id="dept" class="com.zxb.spring5.autowire.Dept"></bean>

byType错误示范:

Could not autowire. There is more than one bean of ‘Dept’ type. Beans: dept,dept. Properties: ‘dept’

因为是根据类型做匹配,但是现在又两个bean,它就不知道去匹配哪一个bean,无法确定用哪一个bean去注入。这种情况下只能使用byName。

<bean id="emp" class="com.zxb.spring5.autowire.Emp" autowire="byType"></bean>
    <bean id="dept" class="com.zxb.spring5.autowire.Dept"></bean>
	<!--不能有多个同种类型的bean对象-->
	<bean id="dept1" class="com.zxb.spring5.autowire.Dept"></bean>

注入属性(外部属性文件)

首先有这么一个场景。当我们创建对象时,往里面注入属性需要property属性来设置name 和 value值,那么当属性特别多的时候,设置起来就很麻烦。以后如果属性发生改变还需要修改xml文件,这样并不是很方便。所以我们一般将比较固定的值放在一个其他的文件当中,比如放到property文件中,然后引入到xml中。比如操作数据库的时候就是把固定的值放在properties文件当中。

​ 1、直接配置数据库信息

​ 配置德鲁伊连接池

​ 引入德鲁伊连接池jar包

<!--直接配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://3306/test"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

这种方式数据都是写死的。

​ 2、引入外部属性配置数据库信息

​ (1)创建外部属性文件,properties格式文件,里面写数据库配置信息。

这里为了减少单词冲突,加上pro.的前缀

pro.driverClass=com.mysql.cj.jdbc.Driver
pro.url=jdbc:mysql://3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
pro.username=root
pro.password=root

​ (2)把外部properties属性文件引入到spring配置文件

​ 引入context名称空间。引入namespace(命名空间)其实就是为了解析那个标签,Spring默认引入的只有四个默认的标签。

<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"
       xmlns:util="http://www.springframework.org/schema/util"
       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/util/spring-util.xsd
                           http://www.springframework.org/schema/context/spring-context.xsd">

​ (3)在Spring配置文件使用标签引入外部文件

<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>

​ 因为我的文件放置在src下,所以就是classpath下的jdbc.properties。src下就是类路径下。

通过${}表达式来获取properties中对应key的值。{}中写的就是properties中key的值。

<!--引入外部属性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${pro.driverClass}"/>
        <property name="url" value="${pro.url}"></property>
        <property name="username" value="${pro.username}"></property>
        <property name="password" value="${pro.password}"></property>
    </bean>

这种场景经常用于数据库的配置中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值