spring5详解-xml方式

一、spring框架概述和简单入门:

思维导图总结:
在这里插入图片描述

在这里插入图片描述

(1)、spring简单介绍:

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
优点:

1.非侵入式设计
Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。
2.方便解耦、简化开发
Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给Spring容器的管理,大大的降低了组件之间的耦合性。
3.支持AOP
Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事物、日志等进行集中式处理,从而提高了程序的复用性。
4.支持声明式事务处理
只需要通过配置就可以完成对事物的管理,而无须手动编程。
5.方便程序的测试
Spring提供了对Junit4的支持,可以通过注解方便的测试Spring程序。
6.方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支持。
7.降低Jave EE API的使用难度。
Spring对Java EE开发中非常难用的一些API(如JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。

(2)、spring的第一个小案例:

第一步:下载spring5的依赖jar包。
下载地址:https://repo.spring.io/release/org/springframework/spring/
下载后的jar包在libs下找。有四个基本包。

在这里插入图片描述
在这里插入图片描述
第二步:打开idea,创建普通java工程。
在这里插入图片描述
在这里插入图片描述
第三步:导入spring5的基本包:
在项目下(与src并列)创建lib文件夹。放jar包

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
模块中导入jar
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
设置文件编译(compile)输出位置:
在这里插入图片描述
第四步:利用spring5创建对象:
在这里插入图片描述

4.1 创建一个java类User(在src下创建一个多级目录,然后在其中创建类User)

package com.fan.springtest;

public class User {
    public void add() {
        System.out.println("add---");
    }
}

此类我们一般用于创建对象。不用spring框架的时候我们用new的方式。
此时用spring框架我们不用new方式创建对象了。

4.2 先创建spring的xml文件(src下创建):

<?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">

    <!--配置User对象创建,class="com.fan.springtest.User"指定User的绝对路径-->
   <bean id="user" class="com.fan.springtest.User">
    </bean>
</beans>

在这里插入图片描述

在这里插入图片描述
第五步:
编写测试代码(单独创建一个测试文件夹《可以任意位置》):
在这里插入图片描述

package testspring;


import com.fan.springtest.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {
    @Test
    public void test01() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user);
        System.out.println("===");
        user.add();

    }

}

测试结果:

com.fan.springtest.User@2e385cce
add—

小结:这里我们并没有手动创建User的实例(对象),是Spring通过ApplicationContext帮我们创建的放在IoC容器里。ApplicationContext是一个IoC容器接口,它所创建的对象都称作是bean,也就是xml文件里的这行配置信息。getBean方法就是从IoC容器里取得这个对象(根据标识id 和类名class),然后我们就可以调用该类的方法

二、IOC容器:

(1)、IOC概念:

spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合。

IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦。如下图:
在这里插入图片描述

大家看到了吧,由于引进了中间位置的“第三方”,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了,全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。

我们再来做个试验:把上图中间的IOC容器拿掉,然后再来看看这套系统:
在这里插入图片描述

我们现在看到的画面,就是我们要实现整个系统所需要完成的全部内容。这时候,A、B、C、D这4个对象之间已经没有了耦合关系,彼此毫无联系,这样的话,当你在实现A的时候,根本无须再去考虑B、C和D了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现IOC容器,对于系统开发而言,这将是一件多么美好的事情,参与开发的每一成员只要实现自己的类就可以了,跟别人没有任何关系!

我们再来看看,控制反转(IOC)到底为什么要起这么个名字?我们来对比一下:

软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。

软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。

通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
在这里插入图片描述

(2)、IOC底层原理:

在这里插入图片描述

IOC过程:

1.在xml中配置创建的对象。
2.创建工厂类,在其中进行xml解析,解析出bean的完整类路径.
3.在工厂类中,使用类的完整路径进行反射创建类的对象。

在这里插入图片描述

在这里插入图片描述
IOC(接口):
在这里插入图片描述
其中FileSystemXmlApplicationContext的实现类的参数是写盘符目录,根据盘符目录去加载文件。
ClassPathXmlApplicationContext参数的类路径,是根据src下的类路径去加载配置文件。

(3)、IOC操作:Bean管理

1.Bean管理指的是两个操作:(1)Spring的创建对象和(2)Spring的注入属性值。

2.Bean管理操作有两种方式

1.基于xml配置文件方式实现
2.基于注解方式实现

Bean操作方式一:基于xml的方式

1.基于xml方式创建对象:

在这里插入图片描述
(1)在spring配置文件中,使用bean标签,标签里面添加对应的属性,就可以实现对象创建。
(2)在bean标签有很多属性,介绍常用属性

id属性:唯一标识。
class属性:l类全路径名(包类路径)

(3)创建对象的时候。默认也是执行的无参构造完成对象的创建。

2.基于xml方式注入属性:

(1)DI:依赖注入,就是注入属性(在创建对象的基础上才能注入属性)

DI(依赖注入):

在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的

比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

依赖注入的方式:

在这里插入图片描述
第一种注入方式:使用set方式进行注入
第一步:创建类(创建对象的模板-类),定义属性和对应的set方法
代码:

package com.fan.springtest;

public class User {
    private String name;
    private int age;

    //setter和getter方法
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

    public void add() {
        System.out.println("add---");
    }
}

第二步:在sping配置文件中配置对象的创建然后配置属性注入。
代码:

<?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">

    <!--1.配置User的创建-->
    <bean id="user" class="com.fan.springtest.User">
        <!--2.使用property完成属性注入
        name:类里面属性名称
        value:向属性注入的值
        -->
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
    </bean>
</beans>

测试:

package testspring;


import com.fan.springtest.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestSpring5 {
    @Test
    public void test01() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user.toString());//测试属性是否注入成功
        System.out.println("===");
        user.add();

    }

}

结果能显示注入成功。
在这里插入图片描述
第二种注入方式:使用有参构造进行注入
(1)创建类,定义属性,创建属性对应的有参构造
代码:

package com.fan.springtest;

public class Order {
    //使用有参构造来注入
    private String oname;
    private String addr;
    //有参构造器
    public Order(String oname, String addr) {
        this.oname = oname;
        this.addr = addr;
    }
    //toString测试方法

    @Override
    public String toString() {
        return "Order{" +
                "oname='" + oname + '\'' +
                ", addr='" + addr + '\'' +
                '}';
    }
}

(2)在spring配置文件中进行配置
代码如下:

<!--使用有参构造来注入-->
    <bean id="order" class="com.fan.springtest.Order">
        <constructor-arg name="oname" value="电脑"></constructor-arg>
        <constructor-arg name="addr" value="西安"></constructor-arg>
    </bean>

最后进行测试:

//测试有参构造器注入
        Order order = context.getBean("order", Order.class);
        System.out.println(order.toString());//测试属性是否注入成功
        System.out.println("===");

3.p名称空间注入(本质set注入)(了解)
使用p名称空间注入,可以简化基于xml配置方式,底层用的还是 set注入。
第一步:添加p名称在配置文件中
第二步:进行属性注入,在bean标签里面进行操作。

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

在这里插入图片描述

4.注入其他类型的属性:
总结:普通属性注入使用property内的name–value搭配给属性赋值
在这里插入图片描述

在这里插入图片描述

4.1注入外部bean类型属性:
总结:在属性property内,name-ref成对出现

(1)创建两个类service和dao类(这里使用Person和Food类演示)

(2)在service中声明类类型dao,并调用dao里面的方法(这里代码简单用其他类演示);
(3)在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">

    <!--1.配置对象的创建-->
    <bean id="person" class="com.fan.domain.Person">
        <!--2.使用property完成属性注入
        name:类里面属性名称
        ref:创建对象bean标签的id值
        -->
        <property name="name" value="张三"></property>
        <property name="food" ref="food"></property>
    </bean>

    <bean id="food" class="com.fan.domain.Food"></bean>

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
4.2注入内部bean类型属性:
总结:在属性property内,name–bean成对出现

Person类:

package com.fan.domain;

public class Person {
    private String name;
    private Food food;

    public String getName() {
        return name;
    }

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

    public Food getFood() {
        return food;
    }

    public void setFood(Food food) {
        this.food = food;
    }

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

Food类:

package com.fan.domain;

public class Food {
    private String name="蔬菜";//食物名称

    public String getName() {
        return name;
    }

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

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

配置文件代码:

<?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">

    <!--1.配置对象的创建-->
    <bean id="person" class="com.fan.domain.Person">
        <!--2.使用property完成属性注入
        name:类里面属性名称
        ref:创建对象bean标签的id值
        -->
        <property name="name" value="张三"></property>
        <property name="food">
            <!--内嵌一个完整的bean-->
            <bean id="food" class="com.fan.domain.Food">
                <property name="name" value="蔬菜"></property>
            </bean>
        </property>
    </bean>


</beans>

测试:

package testspring;

import com.fan.domain.Person;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBean {
    @Test
    public void test01(){
        //加载配置文件
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        //通过配置文件获取对象
        Person person = context.getBean("person", Person.class);
        System.out.println(person);
    }
}

4.3注入属性:级联赋值
第一种级联赋值:(需要类中有set方法)
在这里插入图片描述

第二种级联赋值:(需要类中有set,get方法)
在这里插入图片描述

4.4注入数组,集合类型属性(xml注入数组、集合属性):

集合类型这里例举四类: 数组, List, Map, Set, 其中每一种在xml文件中都有对应的配置方法, 举例说明如下:

创建Person类,定义数组,list,map,set类型属性,生成对应的set方法:


public class Person {

    //1.数组类型属性
    private String[] array;

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

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

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

    public void setArray(String[] array) {
        this.array = array;
    }

    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;
    }

    public void test(){
        System.out.println(Arrays.toString(array));
        System.out.println(list);
        System.out.println(map);
        System.out.println(set);
    }
}

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.ryan.spring5.inputCollection.Person">
    <!--这里泛型等值都是String类型,直接写值就可以-->
        <!--数组类型属性注入-->
        <property name="array">
            <array>
                <value>arr1</value>
                <value>arr2</value>
            </array>
        </property>

        <!--list类型属性注入-->
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
            </list>
        </property>

        <!--map类型属性注入-->
        <property name="map">
            <map>
                <entry key="map-key1" value="map-value1"></entry>
                <entry key="map-key2" value="map-value2"></entry>
            </map>
        </property>

        <!--set类型属性注入-->
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
            </set>
        </property>
    </bean>
</beans>

测试:

public class Test {

    public static void main(String[] args) {

       ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Person person= context.getBean("person", Person.class);

        person.test();
    }
}

在集合里面设置对象类型值
创建Family类:

public class Family {
    private String calling;//成员称呼

    public void setCalling(String calling) {
        this.calling = calling;
    }

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

在Person类中添加内容为对象的集合类型:

...
    //5.内容为对象的list集合类型属性
    private List<Family> families;

    public void setFamilies(List<Family> families) {
        this.families = families;
    }
...

在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.fan.spring5.inputCollection.Person">
        <!--数组类型属性注入-->
        <property name="array">
            <array>
                <value>arr1</value>
                <value>arr2</value>
            </array>
        </property>

        <!--list类型属性注入-->
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
            </list>
        </property>

        <!--map类型属性注入-->
        <property name="map">
            <map>
                <entry key="map-key1" value="map-value1"></entry>
                <entry key="map-key2" value="map-value2"></entry>
            </map>
        </property>

        <!--set类型属性注入-->
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
            </set>
        </property>

        <!--内容为对象的list类型属性注入-->
        <property name="families">
            <list>
            <!--集合中引用多个对象-->
                <ref bean="father"></ref>
                <ref bean="mother"></ref>
            </list>
        </property>

    </bean>

 <!--创建的多个对象-->
    <bean id="father" class="com.fan.spring5.inputCollection.Family">
        <property name="calling" value="father"></property>
    </bean>

    <bean id="mother" class="com.fan.spring5.inputCollection.Family">
        <property name="calling" value="mother"></property>
    </bean>
</beans>

把集合注入部分提取出来
创建Friends类(作为集合添加的对象使用):

public class Friends {

    private List<String> name;

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

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

}

Person类中添加:

//6.提取出来的list集合属性
    private List<Friends> friends;

    public void setFriends(List<Friends> friends) {
        this.friends = friends;
    }

修改配置文件, 配置名称空间, 配置公共对象, 注入对象:
第一步:在spring配置文件中引入名称空间util
第二步:使用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: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 http://www.springframework.org/schema/util/spring-util.xsd"> ****配置名称空间第二步****

    <!--1.提取list集合类型属性注入-->
    <util:list id="friendsList">
        <value>张辽</value>
        <value>太史慈</value>
        <value>Lily</value>
    </util:list>

    <!--2.提取list集合类型属性注入使用-->
    <bean id="friends" class="com.ryan.spring5.inputCollection.Friends">
        <property name="name" ref="friendsList"></property>
    </bean>

    <bean id="ryan" class="com.ryan.spring5.inputCollection.Person">
        <!--数组类型属性注入-->
        <property name="array">
...
...
        <property name="friends" ref="friends"></property>
    </bean>
...

*配置名称空间: 在配置行中添加以下两行即可(复制相应行将关键字改成util即可):

xmlns:util=“http://www.springframework.org/schema/util”

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

测试代码:

在这里插入图片描述

总结DI(依赖注入):

在这里插入图片描述

spring的Bean的分类:

1、普通bean

 <bean  id=""  class="A"> 

spring直接创建A实例,并返回

2、FactoryBean

实现接口的类MyBean:
在这里插入图片描述
配置文件:
在这里插入图片描述
测试类:
在这里插入图片描述

一个特殊的bean,具有工厂生成对象的能力,只能生成特定的对象。bean必须使用 FactoryBean接口,此接口提供方法 getObject() 用于获得特定bean

<bean   id="" class="FB">
 //先创建FB实例,使用调用getObject()方法,并返回方法的返回值
FB fb = new FB();
return fb.getObject();

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

Bean的作用域:

spring 支持几种 bean 的作用域?
在这里插入图片描述

当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
equest:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效
其中比较常用的是singleton和prototype两种作用域。对于singleton作用域的Bean,每次请求该Bean都将获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。

如果不指定Bean的作用域,Spring默认使用singleton作用域。Java在创建Java实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,prototype作用域Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成功,可以重复使用。因此,除非必要,否则尽量避免将Bean被设置成prototype作用域。

常用的分为:单实例和多实例
1.在spring里面,默认情况下,bean是单实例对象。
在这里插入图片描述
2.如何设置单实例还是多实例:
(1)在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例的
(2)scope属性的值
第一个值 默认值 ,singleton,表示的是单实例对象
第二个值 prototype,表示的是多实例对象

xml中的配置:
在这里插入图片描述
(3)singleton和prototype的区别:
第一个:singleton设置单实例,prototype用于设置多实例。
第二个:创建对象的时机不一样,singleton是加载spring配置文件(new ClassPathXmlApplicationContext(“bean2.xml”);)的时候就会创建单实例对象。而prototype是在调用getBean方法的时候创建多实例对象。
其他作用域:
在这里插入图片描述

IOC中Bean的生命周期:

在这里插入图片描述

5步的:

第一步,创建bean实例
第二步,通过set方法为bean的属性赋值
第三部,调用bean的初始化方法
第四步:对象的使用
第五步,调用bean的销毁方法

在这里插入图片描述
代码演示bean的生命周期:

定义一个类Order:

package com.fan.domain;

public class Order {
    private String oname;

    //无参构造
    public Order() {
        System.out.println("第一步,创建bean实例");
    }

    //setter方法
    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步,通过set方法为bean的属性赋值");
    }
    //自定义的初始化方法
    public void initMethod(){
        System.out.println("第三部,调用bean的初始化方法");
    }

    //自定义的销毁方法
    public void destroyMethod(){
        System.out.println("第五步,调用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">

    <!--1.配置User的创建-->
    <bean id="order" class="com.fan.domain.Order" init-method="initMethod" destroy-method="destroyMethod">
        <!--2.使用property完成属性注入
        name:类里面属性名称
        value:向属性注入的值
        -->
        <property name="oname" value="苹果手机"></property>
    </bean>


</beans>

测试类的编写:

package testspring;

import com.fan.domain.Order;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.xml.transform.Source;

public class TestBeanLiveTime {
    @Test
    public void test01(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        Order order = context.getBean("order", Order.class);
        System.out.println("第四步:对象的使用");
        System.out.println(order);
        context.close();//手动关闭容器时。
    }
}

测试结果:
第一步,创建bean实例
第二步,通过set方法为bean的属性赋值
第三部,调用bean的初始化方法
第四步:对象的使用
com.fan.domain.Order@1500b2f3
第五步,调用bean的销毁方法

7步的:
在这里插入图片描述

编写后置处理器MyEeanPost:在这里插入图片描述

配置后置处理器
在这里插入图片描述
注意,后置处理器在初始化方法的前后执行

Spring中bean的装配方式总结:

bean的装配方式可即为依赖注入的方式
在这里插入图片描述

spring的Beans 的自动装配:

在这里插入图片描述

依赖注入有两种形式:构造器注入和setter注入。也就是我们在xml中写的一堆,如果bean太多我们还这样写基本是要成为码农了,更何况我们还有把有关联的bean装配起来,一旦bean很多,就不好维护了。

为此Spring使用自动装配解决这个问题,开发人员不用关心具体装配哪个bean的引用,识别工作由Spring来完成,因此一般配有自动监测来和自动装配配合完成。自动装配其实就是将依赖注入“自动化”的一个简化配置的操作我们不再需要配置文件中使用ref来显示手动的装配注入一个对象

Spring2.5之后提供了注解方式的自动装配。但是要使用这些注解,需要在配置文件中配置<context:annotation-config />。只有加上这一配置,或者maven中引入javax.annotation-api(@Resource属于这个javax包下的)和spring自带的org.springframework.beans才可以使用注解进行自动装配,默认情况下基于注解的装配是被禁用的。常用的自动装配注解有以下几种:@Autowired,,@Inject,@Qualifier,@Named。

Spring会在上下文中自动寻找,并自动给bean装配属性
(自动装配一般适用于外部bean的注入):

在这里插入图片描述

在这里插入图片描述

自动装配模式
下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用 元素的 autowire 属性为一个 bean 定义指定自动装配模式。

五种自动装配模式

1、no
这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。我们要手动的通过name-ref来注入外部bean(这种方式如果属性特别多,很麻烦,代码量特别大,不建议).如下代码:

 <!--1.配置对象的创建-->
    <bean id="person" class="com.fan.domain.Person">
        <!--2.使用property完成属性注入
        name:类里面属性名称
        ref:创建对象bean标签的id值
        -->
        <property name="name" value="张三"></property>
        <property name="food" ref="food"></property>
    </bean>

    <bean id="food" class="com.fan.domain.Food"></bean>

2、byName

当一个bean节点带有 autowire byName的属性时,将查找其类中所有的set方法名,获得将set去掉并且首字母小写的字符串,然后去spring容器中寻找是否有此字符串名称id的对象。如果有,就取出注入;如果没有,就报空指针异常

在这里插入图片描述

3、byType

该模式表示根据Property的数据类型(Type)自动装配,Spring会总动寻找与属性类型相同的bean,若一个bean的数据类型,兼容另一个bean中Property的数据类型,则自动装配。

注意:使用byType首先需要保证同一类型的对象,在spring容器中唯一,若不唯一会报不唯一的异常。

在这里插入图片描述
4、constructor

使用构造方法完成对象注入,其实也是根据构造方法的参数类型进行对象查找,相当于采用byType的方式。即Spring会寻找与参数数据类型相同的bean,通过构造函数将其注入。
在这里插入图片描述

5、default

表示默认采用上一级标签的自动装配的取值。如果存在多个配置文件的话,那么每一个配置文件的自动装配方式都是独立的。

XML 配置里的 Bean 自动装配的缺点
1、在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性,然而,,若只希望装配个别属性时, autowire 属性就不够灵活了。

2、autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之。

3、一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些。

外部属性文件properties

引入外部属性文件配置数据库连接池:
第一步:准备一个德鲁伊的jar包,并放到lib文件夹下。
在这里插入图片描述

第二步:将jar包依赖引入到模块中。
在这里插入图片描述
在这里插入图片描述

第三步:创建外部属性文件,properties格式文件,写数据库信息。
注意!!
db.properties存放在src根目录下。

prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/test
prop.username=root
prop.password=root

注意:properties文件的等号左边的key可以自定义名字,但是为了避免名字冲突带一个前缀prop.也可以是其他单词前缀。

第四步:把外部properties属性文件引入到spring配置文件中(需要引入context名称空间)。让spring帮我们读取配置文件的信息。
·
第五步:在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"
       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/beans/spring-context.xsd">

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

    <!--配置连接池,利用spring表达式${}获取外部文件的值-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClass}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.username}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>


</beans>

在这里插入图片描述

使用注解加载配置文件:

使用@ProtertySource
@PropertySouce是spring3.1开始引入的基于java config的注解。

通过@PropertySource注解将properties配置文件中的值存储到Spring的 Environment中,Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。

2.1 用法1- @PropertySource和@Value
创建java配置类

@Configuration
@PropertySource("classpath:jdbc.properties")
public class PropertiesWithJavaConfig {
   @Value(${jdbc.driver})
   private String driver;
   @Value(${jdbc.url})
   private String url;
   @Value(${jdbc.username})
   private String username;
   @Value(${jdbc.password})
   private String password;
   //要想使用@Value 用${}占位符注入属性,这个bean是必须的,这个就是占位bean,另一种方式是不用value直接用Envirment变量直接getProperty('key')  
   @Bean
   public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
      return new PropertySourcesPlaceholderConfigurer();
   }
}

2.2 用法2-通过Environment设置

@Configuration
@PropertySource("classpath:jdbc.properties")
public class PropertiesWithJavaConfig {

   @Autowired
    private Environment env;

}

接着就可以用env.getProperty(“jdbc.driver”)得到相应的属性值

https://www.cnblogs.com/whx7762/p/7885735.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值