SpringIOC学习笔记整理

IOC(DI)是一个用来管理对象的容器,用来管理对象获取的方式。
DI又叫做依赖注入,可以判断依赖关系。
一个A类,A类有一个父类B类,在javaSE中在创建A类前要先创建B类,再将B类注入到A类中,在Spring中,这一步骤可以由IOC容器来实现。

IOC与DI概述:

  • IOC:其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源。作为为回应,容器适时的返回资源。而应用了IOC之后,则是容器主动的将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源。这种行为也被称为查找的被动形式。
  • DI:IOC的另一种表述方式,即组件以一些预先定义好的方式(例如 set方法)接受来自资源容器的注入。相对于IOC而言,这种表述更直接。

一、初步使用IOC容器

1、hello IOC

创建一个普通的maven工程,导入jar包

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.9.RELEASE</version>
        </dependency>

创建一个User类

package bean;

public class User {
    private String name;
    private int age;
    public User(){}
    public User(int age,String name){
        this.name=name;
        this.age=age;
    }

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

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

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

在resources下创建一个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">
<!--属性注入-->
<!--    id唯一,若是没设id,则通过class="bean.User"来获取容器对象-->
    <bean id="user" class="bean.User">
<!--        实际上是在调用User类中的set方法-->
<!--        name实际上不是属性,而是方法名,只不过将setName中的set去掉且将Name变成小写-->
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>
</beans>

在主方法中创建IOC容器对象

package test;

import bean.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo01 {
    public static void main(String[] args){
        ApplicationContext context=new ClassPathXmlApplicationContext("spring01.xml");
        User user= (User) context.getBean("user");
        System.out.println(user);
    }
}

运行结果:
在这里插入图片描述

2、springIOC的三种注入方式

  • 属性注入
    <bean id="user" class="bean.User">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>
  • 构造器注入
    <bean id="user1" class="bean.User">
<!--        有name属性时,可以不用按照构造器的传参顺序,没有name时,value需要和有参构造器中的参数对应上-->
<!--        没有name时,也可以指定index来强制规定value对应第几个参数-->
<!--        向构造器中参数传值是以数组的方式-->
<!--        <constructor-arg value="张三" index="1"/>-->
<!--        <constructor-arg value="20" index="0"/>-->
        <constructor-arg name="name" value="张三"/>
        <constructor-arg name="age" value="20"/>
    </bean>
  • 通过工厂方法注入
    (1)静态工厂方式
    调用静态工厂方法创建Bean是将对象创建过程封装到静态方法中。
    工厂类:
package test;

import bean.Car;

public class CarFactory {
    private static Car car;
    public static Car getCar(String kind,int price){
        car=new Car();
        car.setKind(kind);
        car.setPrice(price);
        return car;
    }
}

xml:

<!--    class指向工厂类-->
    <bean id="car" class="test.CarFactory" factory-method="getCar">
        <constructor-arg name="kind" value="audi"/>
        <constructor-arg name="price" value="20000"/>
    </bean>

在这里插入图片描述
(2)实例工厂方式
实例工厂方式:将对象的创建过程封装到另一个对象的实例方法里
工厂类:

package test;

import bean.Car;

public class BeanFactory {
    private Car car;
    public Car getCar(String kind,int price){
        car=new Car();
        car.setPrice(price);
        car.setKind(kind);
        return car;
    }
}

xml:

    <bean id="beanFactory" class="test.BeanFactory"/>
    <bean id="car" class="bean.Car" factory-bean="beanFactory" factory-method="getCar">
        <constructor-arg name="kind" value="audi"/>
        <constructor-arg name="price" value="20000"/>
    </bean>

在这里插入图片描述

3、当对象间存在引用关系

(1)添加引用对象属性

Car类:

package bean;

public class Car {
    private String kind;
    private int price;
    public Car(){}
    public Car(String kind,int price){
        this.kind=kind;
        this.price=price;
    }

    public void setKind(String kind) {
        this.kind = kind;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getKind() {
        return kind;
    }

    public int getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "kind='" + kind + '\'' +
                ", price=" + price +
                '}';
    }
}

spring01.xml:

    <bean id="user" class="bean.User">
        <property name="age" value="20"/>
        <property name="name" value="tom"/>
        <property name="car" ref="car"/>
    </bean>
    <bean id="car" class="bean.Car">
        <property name="kind" value="audi"/>
        <property name="price" value="20000"/>
    </bean>

(2)还可以通过内部bean的方式来管理

    <bean id="user" class="bean.User">
        <constructor-arg name="age" value="20"/>
        <constructor-arg name="name" value="tom"/>
        <constructor-arg name="car">
            <bean class="bean.Car">
                <property name="price" value="20000"/>
                <property name="kind" value="audi"/>
            </bean>
        </constructor-arg>
    </bean>

(3)IOC容器支持级联属性

在外层User类中先将Car初始化
在这里插入图片描述
直接通过car对象调用其中的set方法

    <bean id="user" class="bean.User">
        <property name="name" value="tom"/>
        <property name="age" value="20"/>
        <property name="car.kind" value="audi"/>
        <property name="car.price" value="20000"/>
    </bean>

(4)IOC容器支持集合属性

在User类中添加集合属性
在这里插入图片描述

  • 内部list标签
    <bean id="user" class="bean.User">
        <property name="name" value="tom"/>
        <property name="age" value="20"/>
        <property name="cars">
            <list>
                <bean id="car" class="bean.Car">
                    <property name="kind" value="audi"/>
                    <property name="price" value="20000"/>
                </bean>
                <bean id="car" class="bean.Car">
                    <property name="kind" value="BMW"/>
                    <property name="price" value="50000"/>
                </bean>
            </list>
        </property>
    </bean>
  • 外部list标签
    <bean id="car" class="bean.Car">
        <property name="kind" value="audi"/>
        <property name="price" value="20000"/>
    </bean>
    <uril:list id="cars">
        <ref bean="car"/>
        <ref bean="car"/>
        <ref bean="car"/>
        <ref bean="car"/>
    </uril:list>
    <bean id="user" class="bean.User">
        <property name="age" value="20"/>
        <property name="name" value="tom"/>
        <property name="cars" ref="cars"/>
    </bean>

(5)IOC容器支持Map

在这里插入图片描述

    <bean id="user" class="bean.User">
        <property name="age" value="20"/>
        <property name="name" value="tom"/>
        <property name="map" ref="map"/>
    </bean>
    <uril:map id="map">
        <entry key="k1" value-ref="car"/>
        <entry key="k2" value-ref="car"/>
        <entry key="k3" value-ref="car"/>
    </uril:map>

(6)IOC容器支持Set

在这里插入图片描述

    <bean id="user" class="bean.User">
        <property name="age" value="20"/>
        <property name="name" value="tom"/>
        <property name="carSet" ref="set"/>
    </bean>
    <uril:set id="set">
        <ref bean="car"/>
    </uril:set>

(7)IOC容器支持P标签

首先在xml文件首部加上P标签的命名空间

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

    <bean id="car" class="bean.Car" p:kind="audi" p:price="50000"/>
    <bean id="user" class="bean.User" p:car-ref="car"/>

(8)IOC容器支持autowire自动装配

Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 < bean> 的 autowire 属性里指定自动装配的模式

  • byType(根据类型自动装配):
    拿User与Car类来说明
    User类中含有需要Car类型的属性,当在< bean>标签中的autowire指定byType后,会在xml文件中,查找所有含有Car类型的< bean>。若能查找到一个,则将User类中,所有含有Car类型的属性都装配上Car的< bean>;若查找到多个,在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配.
  • byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同.

(9)IOC支持父子bean

在< bean>中添加parent属性,不支持多继承。
当父bean中abstract设为true时,父bean以模板形式存在,不会实例化。

(10)IOC支持depends-on依赖关系

前置依赖的bean会在本bean实例化前创建好。
如果前置依赖多个bean可以通过逗号或空格的方式配置bean的名称。

4、IOC容器对象实例化顺序

在配置文件中,谁先配置谁先初始化

下面的示例中,User被叫做为外层对象,Car叫做被引用的对象

当对象间存在引用关系,且被引用的对象配置在了后面,则先初始化先配置的对象,然后初始化被引用的对象,调用被引用的对象中的set方法,最后调用先配置的对象的set方法。
在这里插入图片描述
当对象间存在引用关系,且被引用的对象配置在了前面,则先初始化被引用的对象,然后调用被引用的对象中的set方法,初始化外层的对象,最后调用外层对象的set方法。
在这里插入图片描述
当对象间不存在引用关系,按照配置顺序依次实例化,先初始化前面的对象并调用他的set方法,然后再初始化后面的对象并调用他的set方法。
在这里插入图片描述
在这里插入图片描述

5、IOC容器中bean的生命周期

IOC容器可以管理bean的生命周期。
Spring IOC允许在 Bean 生命周期的特定点执行定制的任务.
Spring IOC 容器对 Bean 的生命周期进行管理的过程:

  • 通过构造器或工厂方法创建 Bean 实例
  • 为 Bean 的属性设置值和对其他 Bean 的引用
  • 调用 Bean 的初始化方法
  • Bean 可以使用了
  • 当容器关闭时, 调用 Bean 的销毁方法

在 Bean 的声明里设置 init-method 和 destroy-method 属性, 为 Bean 指定初始化和销毁方法.
初始化:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
销毁:
在这里插入图片描述

6、创建Bean后置处理器

Bean后置处理器允许在调用初始化方法前后对Bean进行额外处理,处理原理类似于Servlet中的过滤器

package test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class CarPost implements BeanPostProcessor {
    //o是bean实例化出来的对象
    //s是bean中的id
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("Before  o是:"+o+"  s是:"+s);
        return o;
    }

    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("After  o是:"+o+"  s是:"+s);
        return 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="car" class="bean.Car" init-method="init" destroy-method="destroy">
        <property name="price" value="20000"/>
        <property name="kind" value="audi"/>
    </bean>
    <bean class="test.CarPost"/>
</beans>

在这里插入图片描述

二、通过IOC容器配置数据库连接池

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: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="classpath:db.properties"></context:property-placeholder>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
        <property name="initialSize" value="${db.initNum}"/>
        <property name="maxActive" value="${db.maxNum}"/>
    </bean>
</beans>

外部文件:
在这里插入图片描述

三、spring组件扫描

spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件。
可以将带有注解的类,注入到IOC容器当中,这些类受IOC容器管理

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

<!--    自动扫描指定包以及子包下所有添加了注解的类,然后加入到IOC容器当中-->
    <context:component-scan base-package="spring"></context:component-scan>
</beans>

可以设置只扫描特定的类:

<!--    设置只扫描时,需更改扫描规则use-default-filters="false"-->
    <context:component-scan base-package="spring" use-default-filters="false">
<!--        只扫描特定注解的类-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--        只扫描自己写的某个类-->
        <context:include-filter type="assignable" expression="spring.controller.UserController"/>
    </context:component-scan>

可以设置扫描时排除的类

    <context:component-scan base-package="spring">
        <!--        只排除特定注解的类-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--        只排除自己写的某个类-->
        <context:exclude-filter type="assignable" expression="spring.controller.UserController"/>
    </context:component-scan>

特定组件包括:

  • @Component:基本注解,标识了一个受spring管理的组件
  • @Repository:标识持久层组件
  • @Service:标识服务层(业务层)组件
  • @Controller:标识表现层组件
  • @Autowired:自动注入,会将IOC容器中的对象自动注入给我们要使用的对象当中。注意,使用这个注解的前提是,要被注入的那个对象所在的类要受IOC容器管理。

使用getBean获取类对象的方法是让类名第一个字母小写,等价于< bean>中的id属性
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值