IOC介绍



IOC容器

  1. 控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
  2. 使用目的:降低耦合度


IOC底层原理
1、在 Spring的配置文件中,配置创建的对象
2、设计一个工厂模式的类,类中利用 xml解析技术(dom4j) 取出类的全路径,并通过反射技术,返回一个该类的对象
3、其他类可以通过工厂类,来获得其他对象,从而实现对象与对象之间的调用
在这里插入图片描述


IOC接口

  • IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
  • Spring 提供 IOC 容器实现两种方式:(两个接口)

(1)、BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用

  • 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象

(2)、ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人
员进行使用

  • 加载配置文件时候就会把在配置文件对象进行创建



IOC操作Bean管理

  1. 什么是 Bean 管理
    • Spring 创建对象
    • Spirng 注入属性
  2. Bean 管理操作有两种方式
    • 基于 xml 配置文件方式实现
    • 基于注解方式实现



IOC 操作 Bean 管理(基于 xml 方式)

创建对象

  1. 在 Spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建
  2. 在 bean 标签有很多属性,介绍常用的属性
    • id 属性:唯一标识
    • class 属性:类全路径(包类路径)
  3. 创建对象时候,默认执行无参数构造方法完成对象创建

注入方式
1、set 方法
类中需提供属性的set方法

    <!--1、bean标签创建对象-->
    <bean id="book" class="com.study.spring5.Book">
        <!--2、使用property完成属性注入
            name: 类里面属性名称
            value: 向属性注入的值
        -->
        <property name="bname" value="西游记"></property>
    </bean>        

2、使用 有参构造 进行注入
类中需提供 有参 构造

    <!--有参构造注入属性-->
    <bean id="orders" class="com.study.spring5.Orders">
        <constructor-arg name="oname" value="上海"></constructor-arg>
    </bean>

3、使用p名称空间 进行注入
在Spring的配置文件中,添加 p 名称空间
在这里插入图片描述

<bean id="book" class="com.study.spring5.Book" p:bname="三国演义" p:bauthor="罗贯中"></bean>


注入空值和特殊字符
注入空值

    <bean id="userDao" class="com.study.spring5.dao.UserDaoImpl">
        <property name="bname">
            <null/>
        </property>
    </bean>

注入特殊字符

    <bean id="book" class="com.study.spring5.Book">
        <property name="bname" value="西游记"></property>
        <property name="address">
            <value><![CDATA[<<上海>>]]></value>
        </property>
    </bean>


注入属性:外部bean
一个类中 定义了 另一个 类 的属性

    <!--1 service 和 dao 对象创建-->
    <bean id="userService" class="com.study.spring5.service.UserService"></bean>
        <!--注入 userDao 对象
            name 属性:类里面属性名称
            ref 属性:创建 userDao 对象 bean 标签 id 值
        -->
        <property name="userDao" ref="userDaoImpl"></property>
    <!--接口不能创建,class要填写它的实现类-->
    <bean id="userDaoImpl" class="com.study.spring5.dao.UserDaoImpl"></bean>


注入属性:内部bean
效果与 外部bean 相同(一个类包含另一个类的对象),只是 配置bean在Spring配置文件中的位置不同

    <!--内部bean-->
    <bean id="emp" class="com.study.spring5.bean.Emp">
        <!--设置对象类型属性-->
        <!--把dept放到外面,以外部bean的方式创建,也可以使用,只不过这里演示的是内部bean的创建-->
        <!--外部bean 和 内部bean 是已在配置文件中 创建bean的位置来决定的-->
        <property name="dept">
            <bean id="dept" class="com.study.spring5.bean.Dept">
                <property name="dname" value="职工"></property>
            </bean>
        </property>
    </bean>


注入属性:级联赋值
级联赋值:是在一个bean对象中注入另一个bean对象(外部bean)的属性并对该属性进行赋值。
第一种写法

    <bean id="emp" class="com.study.spring5.bean.Emp">
        <property name="dept" ref="dept"></property>
    </bean>

    <bean id="dept" class="com.study.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>
    </bean>

第二种写法

    <bean id="emp" class="com.study.spring5.bean.Emp">
        <property name="dept" ref="dept"></property>
        <property name="dept.dname" value="技术部"></property>
    </bean>

    <bean id="dept" class="com.study.spring5.bean.Dept"></bean>


注入集合属性
注入数组

    <bean id="stu" class="com.study.spring5.collectiontype.Stu">
        <!--数组类型属性注入-->
        <property name="courses">
            <array>
                <value>Java课程</value>
                <value>数据库课程</value>
            </array>
        </property>
    </bean>        

注入list

    <bean id="stu" class="com.study.spring5.collectiontype.Stu">
        <!--数组类型属性注入-->
        <property name="list">
            <list>
                <value>张三</value>
                <value>李四</value>
            </list>
        </property>
    </bean>                

注入set

    <bean id="stu" class="com.study.spring5.collectiontype.Stu">
        <property name="set">
            <set>
                <value>MySQL</value>
                <value>Redis</value>
            </set>
        </property>  
    </bean>            

注入map

    <bean id="stu" class="com.study.spring5.collectiontype.Stu">
        <property name="maps">
            <map>
                <entry key="JAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>    
    </bean>    


集合里面设置对象值

    <bean id="stu" class="com.study.spring5.collectiontype.Stu">
        <property name="courseList">
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>
    </bean>
    
    <bean id="course1" class="com.study.spring5.collectiontype.Course">
        <property name="cname" value="Spring5框架"></property>
    </bean>
    
    <bean id="course2" class="com.study.spring5.collectiontype.Course">
        <property name="cname" value="MyBatis框架"></property>
    </bean>


将集合提取出去,使之成为公共部分

添加util名称空间

<!--添加xmlns: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">

提取集合,并注入

    <!--1 提取list集合类型属性注入-->
    <util:list id="bookList">
        <!--如果集合里面是对象值,用<ref标签>-->
        <!--<ref bean="course1"></ref>-->
        <value>西游记</value>
        <value>三国演义</value>
        <value>红楼梦</value>
    </util:list>

    <!--2 提取list集合类型属性注入使用-->
    <!--集合类型以及泛型必须一致或兼容-->
    <bean id="book" class="com.study.spring5.collectiontype.Book">
        <property name="list" ref="bookList"></property>
    </bean>



Bean管理(工厂bean)
1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)

2、普通 bean:在配置文件中定义 bean 类型就是返回类型

3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样


Bean的作用域
1、在 Spring 里面,设置创建 bean 实例是单实例还是多实例

2、在 Spring 里面,默认情况下,bean 是单实例对象


设置对象为多实例

  1. 在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
  2. scope 属性值
    ● singleton:默认值,表示是单实例对象
    ● prototype:表示是多实例对象

singleton 和 prototype 区别

  1. singleton 单实例,prototype 多实例
  2. 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
    设置 scope 值是 prototype 时候,调用 getBean 方法时候创建多实例对象
    <bean id="book" class="com.study.spring5.collectiontype.Book" scope="prototype">
        <property name="list" ref="bookList"></property>
    </bean>



Bean生命周期

  • 生命周期:从对象创建到对象销毁的过程

Bean 生命周期
1、通过构造器创建 bean 实例(无参数构造)
2、为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
3、调用 bean 的初始化的方法(需要进行配置初始化的方法)
4、bean 可以使用了(对象获取到了)
5、当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

在类中创建执行初始化和执行销毁的方法

    //创建执行的初始化的方法
    public void initMethod() {
        System.out.println("第三步 执行初始化方法");
    }

    public void destroyMethod(){
        System.out.println("第五步 执行销毁方法");
    }
    <bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手机"></property>
    </bean>

测试时,需手动销毁

        //手动让bean实例销毁
        ((ClassPathXmlApplicationContext) context).close();


后置处理器

  • 如果添加了后置处理器,那么Bean的生命周期有七步

1、通过构造器创建 bean 实例(无参数构造)
2、为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
3、把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
4、调用 bean 的初始化的方法(需要进行配置初始化的方法)
5、把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
6、bean 可以使用了(对象获取到了)
7、当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

创建类,实现接口 BeanPostProcessor,创建后置处理器

public class MyBeanPost implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        return bean;
    }
}

在配置文件中配置了后置处理器,那么会为在配置文件中所有bean都添加后置处理器

    <bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手机"></property>
    </bean>

    <!--配置后置处理器-->
    <bean id="myBeanPost" class="com.study.spring5.bean.MyBeanPost"></bean>


自动装配
根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入

    <!--实现自动装配
    bean标签属性autowire,配置自动装配
    autowire属性常用两个值:
                byName根据属性名称注入,注入值bean的id值和类属性名称一样
                byType根据属性类型注入
    -->
    <bean id="emp" class="com.study.spring5.autowire.Emp" autowire="byName"></bean>
    
    <bean id="dept" class="com.study.spring5.autowire.Dept"></bean>


引入外部属性文件
加入 context 名称空间

<!--引入xmlns:context 和 spring-context.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: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">
    <!--引入外部文件-->
    <!--classpath: 指的是src目录下-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClass}" />
        <property name="url" value="${prop.url}" />
        <property name="username" value="${prop.username}" />
        <property name="password" value="${prop.password}" />
    </bean>


IOC操作 Bean管理(基于注解方式)

创建对象

  • @Component:普通组件
  • @Service:一般用于业务逻辑层或service层上
  • @Controller:一般用于web层
  • @Repository:一般用于dao层

上面四个注解功能是一样的,都可以用来创建 bean 实例


1、引入aop依赖
在这里插入图片描述
2、添加名称空间 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:p="http://www.springframework.org/schema/p"
       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">

3、开启组件扫描

    <!--开启组件扫描
        base-package: 要扫描那个包
        1 如果扫描多个包,多个包使用逗号隔开
        2 扫描包上层目录(多个注解类在同一个包下)
    -->
    <context:component-scan base-package="com.study.spring5"></context:component-scan>

4、创建类,在类上面添加创建对象注解

//@Component(value = "userService") 等同于 <bean id="userService" class="com.study.spring5.service.UserService"></bean>
//注解后面的 values 是设置 id
//class 不需要指定,因为开启组件扫描,Spring扫描到这,发现是bean,自然会得到这个类的全路径

//在注解里面value属性值可以省略不写,
//默认值是类名称,首字母小写
//UserService -- userService
@Component(value = "userService")
public class UserService {
    public void add() {
        System.out.println("UserService调用了add.......");
    }
}



组件扫描细节配置

    <!-- 实例1
        use-default-filters: 表示不使用默认filter,而使用自己配置filter
        context:include-filter: 配置规则(设置扫描那些内容)
        type="annotation": 类型为注解
        expression="org.springframework.stereotype.Controller": 表示扫描类型为Controller的注解
        整体意思: 只扫描在com.study包下的 注解类型为 Controller 的 类
    -->
    <context:component-scan base-package="com.study" use-default-filters="false">
        <context:include-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <!--实例2
        context:exclude-filter type="annotation": 设置不包含那些注解
        整体意思: 扫描com.study包下 不包含 Controller 的 所有注解
    -->
    <context:component-scan base-package="com.study">
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>



基于注解方式实现属性注入

  1. @Autowired:根据属性类型进行自动装配
  2. @Qualifier:根据名称进行注入
  3. @Resource:可以根据类型注入,可以根据名称注入
  4. @Value:注入普通类型属性


@Autowired:根据属性类型进行自动装配

@Service
public class UserService {

    //定义dao类型属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired //根据类型注入
    private UserDao userDao;

    public void add() {
        System.out.println("UserService调用了add.......");
        userDao.add();
    }
}

@Qualifier:根据名称进行注入
这个@Qualifier 注解的使用,和上面@Autowired一起使用

@Autowired 是根据 属性类型来注入,但如果有多个相同类型的bean,使用这个注解就麻烦了,比如接口的实现类

因此,使用 @Qualifier 通过名称(注解设置的 value) 就可以很好的解决这个问题

//默认的value是 类的名称(第一个字母小写)
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao {
}
public class UserService {
    @Autowired //根据类型注入
    @Qualifier(value = "userDaoImpl1") //指定value
    private UserDao userDao;

@Resource:可以根据类型注入,可以根据名称注入

//类型注入
    @Resource
    private UserDao userDao;
//名称注入
    @Resource(name = "userDaoImpl1")
    private UserDao userDao;

@Value:注入普通类型属性

    @Value("张三")
    private String name;



完全注解开发
创建配置类,替代 xml 配置文件

@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = "com.study.spring5")
public class SpringConfig {

}

测试时,这样获取

ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);



IOC容器

1、什么是 IOC
(1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理
(2)使用 IOC 目的:为了耦合度降低

底层原理

2、IOC 底层原理
(1)xml 解析、工厂模式、反射
在这里插入图片描述
在这里插入图片描述

1、在 Spring.xml文件中,配置创建的对象
2、设计一个工厂模式的类,类中利用 xml解析技术(dom4j) 取出类的全路径,并通过反射技术,返回一个该类的对象
3、其他类可以通过工厂类,来获得其他对象,从而实现对象与对象之间的调用
在这里插入图片描述

IOC接口

1、IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂
2、Spring 提供 IOC 容器实现两种方式:(两个接口)

(1)BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用

  • 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象

(2)ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人
员进行使用

  • 加载配置文件时候就会把在配置文件对象进行创建

3、ApplicationContext 接口有实现类
FileSystemXmlApplicationContext:系统盘下的Spring 配置的 xml文件
ClassPathXmlApplicationContext:src目录下的Spring 配置的 xml文件
在这里插入图片描述

IOC操作Bean管理

1、什么是 Bean 管理
(0)Bean 管理指的是两个操作
(1)Spring 创建对象
(2)Spirng 注入属性

2、Bean 管理操作有两种方式
(1)基于 xml 配置文件方式实现
(2)基于注解方式实现

IOC 操作 Bean 管理(基于 xml 方式)

1、基于 xml 方式创建对象

(1)在 spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建

(2)在 bean 标签有很多属性,介绍常用的属性

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

(3)创建对象时候,默认也是执行无参数构造方法完成对象创建

第一种注入方式:使用 set 方法进行注入

Book属性

public class Book {
    //创建对象
    private String bname;
    private String bauthor;

    //创建对应的set方法
    public void setBname(String bname) {
        this.bname = bname;
    }

    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }
    
    public void testDemo() {
        System.out.println(bname + "::" + bauthor);
    }
}

spring对应的xml文件

    <!--1、bean标签创建对象-->
    <bean id="book" class="com.study.spring5.Book">
        <!--2、使用property完成属性注入
            name: 类里面属性名称
            value: 向属性注入的值
        -->
        <property name="bname" value="西游记"></property>
        <property name="bauthor" value="吴承恩"></property>
    </bean>

测试

    @Test
    public void bookTest(){
        //1.加载spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2.获取配置创建的对象
        Book book = context.getBean("book", Book.class);
        //3.输出
        book.testDemo();
    }

在这里插入图片描述

第二种注入方式:使用 有参构造 进行注入

Orders

public class Orders {
    private String oname;
    private String address;


    //有参构造
    public Orders(String oname, String address) {
        this.oname = oname;
        this.address = address;
    }

    public void ordersTest() {
        System.out.println(oname + "::" + address);
    }
}

spring对应的xml文件

    <!--有参构造注入属性-->
    <bean id="orders" class="com.study.spring5.Orders">
        <constructor-arg name="oname" value="上海"></constructor-arg>
        <constructor-arg name="address" value="浦东"></constructor-arg>
    </bean>

ordersTest

    @Test
    public void ordersTest(){
        //1.加载spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        //2.获取配置创建的对象
        Orders orders = context.getBean("orders", Orders.class);
        //3.输出
        orders.ordersTest();
    }

在这里插入图片描述

第三种注入方式:使用 p名称空间 进行注入

(1)使用 p 名称空间注入,可以简化基于 xml 配置方式

1、在配置文件中添加 p 名称空间
在这里插入图片描述
2、spring对应的xml文件添加<bean>标签
在 bean 标签中进行属性注入

<bean id="book" class="com.study.spring5.Book" p:bname="三国演义" p:bauthor="罗贯中"></bean>

3、测试
在这里插入图片描述

注入空值和特殊字符

注入空值

    <bean id="book" class="com.study.spring5.Book">
        <property name="bname" value="西游记"></property>
        <property name="bauthor" value="吴承恩"></property>
        <!--null 值-->
        <property name="address">
            <null></null>
        </property>
    </bean>

注入特殊字符

    <bean id="book" class="com.study.spring5.Book">
        <property name="bname" value="西游记"></property>
        <property name="bauthor" value="吴承恩"></property>
        <property name="address">
            <value><![CDATA[<<上海>>]]></value>
        </property>
    </bean>

注入属性:外部bean

(1)创建两个类 service 类和 dao 类
(2)在 service 调用 dao 里面的方法
(3)在 spring 配置文件中进行配置

1、先UserService中,定义dao属性

public class UserService {
    //创建 UserDao 类型属性,生成 set 方法
    //UserDao 是一个接口,接口多态
    private UserDao userDao;

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

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

2、在spring的配置文件中,配置使用的 service 和 dao

    <!--1 service 和 dao 对象创建-->
    <bean id="userService" class="com.study.spring5.service.UserService"></bean>

    <!--接口不能创建,class要填写它的实现类-->
    <bean id="userDaoImpl" class="com.study.spring5.dao.UserDaoImpl"></bean>

3、在service的<bean>标签中,注入 dao 属性

    <bean id="userService" class="com.study.spring5.service.UserService">
        <!--注入 userDao 对象
            name 属性:类里面属性名称
            ref 属性:创建 userDao 对象 bean 标签 id 值
        -->
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>

4、测试
在这里插入图片描述

注入属性:内部bean

(1)一对多关系:部门和员工 (多个对象 包含 一个 相同对象)

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

Emp

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

    public void add() {
        System.out.println(ename + "::" + gender + "::" + dept);
    }
}

2、配置spring的配置文件

    <!--内部bean-->
    <bean id="emp" class="com.study.spring5.bean.Emp">
        <!--设置两个普通属性-->
        <property name="ename" value="tom"></property>
        <property name="gender" value=""></property>
        <!--设置对象类型属性-->
        <!--把dept放到外面,以外部bean的方式创建,也可以使用,只不过这里演示的是内部bean的创建-->
        <!--外部bean 和 内部bean 是已在配置文件中 创建bean的位置来决定的-->
        <property name="dept">
            <bean id="dept" class="com.study.spring5.bean.Dept">
                <property name="dname" value="职工"></property>
            </bean>
        </property>
    </bean>

3、测试
在这里插入图片描述

注入属性:级联赋值

级联赋值:是在一个bean对象中注入另一个bean对象(外部bean)的属性并对该属性进行赋值。

第一种写法

    <bean id="emp" class="com.study.spring5.bean.Emp">
        <property name="ename" value="jack"></property>
        <property name="gender" value=""></property>
        <property name="dept" ref="dept"></property>
    </bean>

    <bean id="dept" class="com.study.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>
    </bean>

第二种写法

    <bean id="emp" class="com.study.spring5.bean.Emp">
        <property name="ename" value="jack"></property>
        <property name="gender" value=""></property>
        <property name="dept" ref="dept"></property>
        <property name="dept.dname" value="技术部"></property>
    </bean>

    <bean id="dept" class="com.study.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>
    </bean>

要提供被注入对象的get()方法
在这里插入图片描述

在这里插入图片描述

注入集合属性

在 Stu类中定义数组、list、set、map属性,并提供set()方法
在这里插入图片描述
spring对应的xml文件

    <!--1 集合类型属性注入-->
    <bean id="stu" class="com.study.spring5.collectiontype.Stu">
        <!--数组类型属性注入-->
        <property name="courses">
            <array>
                <value>Java课程</value>
                <value>数据库课程</value>
            </array>
        </property>
        <!--list类型属性注入-->
        <property name="list">
            <list>
                <value>张三</value>
                <value>李四</value>
            </list>
        </property>
        <!--set类型属性注入-->
        <property name="set">
            <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>

测试
在这里插入图片描述

集合里面设置对象值

定义一个 类型为 Course 的 List 集合
在这里插入图片描述
spring对应的xml文件

    <bean id="stu" class="com.study.spring5.collectiontype.Stu">
        <property name="courseList">
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>
    </bean>
    
    <bean id="course1" class="com.study.spring5.collectiontype.Course">
        <property name="cname" value="Spring5框架"></property>
    </bean>
    
    <bean id="course2" class="com.study.spring5.collectiontype.Course">
        <property name="cname" value="MyBatis框架"></property>
    </bean>

在这里插入图片描述

将集合提取出去,使之成为公共部分

在这里插入图片描述

设置:xmlns:util="http://www.springframework.org/schema/util"
设置: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">
    <!--1 提取list集合类型属性注入-->
    <util:list id="bookList">
        <!--如果集合里面是对象值,用<ref标签>-->
        <!--<ref bean="course1"></ref>-->
        <value>西游记</value>
        <value>三国演义</value>
        <value>红楼梦</value>
    </util:list>

    <!--2 提取list集合类型属性注入使用-->
    <!--集合类型以及泛型必须一致或兼容-->
    <bean id="book" class="com.study.spring5.collectiontype.Book">
        <property name="list" ref="bookList"></property>
    </bean>
    
    <bean id="course1" class="com.study.spring5.collectiontype.Course"></bean>

在这里插入图片描述

Bean管理(工厂bean)

1、Spring 有两种类型 bean,一种普通 bean,另外一种工厂 bean(FactoryBean)

2、普通 bean:在配置文件中定义 bean 类型就是返回类型

3、工厂 bean:在配置文件定义 bean 类型可以和返回类型不一样

第一步 创建类,让这个类作为工厂 bean,实现接口 FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的 bean 类型

public class MyBean implements FactoryBean<Course> {
    //定义返回Bean
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("abc");
        //返回一个实例
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        //返回实例类型
        return null;
    }

    @Override
    public boolean isSingleton() {
        //是否是单例
        return false;
    }
}

spring对应的xml文件

    <bean id="myBean" class="com.study.spring5.factoybean.MyBean"></bean>

测试

    @Test
    public void test3() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        //后面的 xx.class 要是 返回类型的class
        Course myBean = context.getBean("myBean", Course.class);
        System.out.println(myBean.getClass());
    }


Bean的作用域

1、在 Spring 里面,设置创建 bean 实例是单实例还是多实例

2、在 Spring 里面,默认情况下,bean 是单实例对象


默认单例对象

    @Test
    public void test4() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book1 = context.getBean("book", Book.class);
        Book book2 = context.getBean("book", Book.class);
        System.out.println(book1);
        System.out.println(book2);
    }

在这里插入图片描述

设置对象为多实例

  1. 在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例

  2. scope 属性值
    ● singleton:默认值,表示是单实例对象
    ● prototype:表示是多实例对象

singleton 和 prototype 区别

  1. singleton 单实例,prototype 多实例
  2. 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
    设置 scope 值是 prototype 时候,调用 getBean 方法时候创建多实例对象
    <bean id="book" class="com.study.spring5.collectiontype.Book" scope="prototype">
        <property name="list" ref="bookList"></property>
    </bean>

在这里插入图片描述

Bean生命周期

1、生命周期
(1)从对象创建到对象销毁的过程

2、bean 生命周期

  1. 通过构造器创建 bean 实例(无参数构造)
  2. 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
  3. 调用 bean 的初始化的方法(需要进行配置初始化的方法)
  4. bean 可以使用了(对象获取到了)
  5. 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

Orders类

public class Orders {
    private String oname;

    public Orders() {
        System.out.println("第一步 执行无参构造创建bean对象");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步 调用set方法设置属性值");
    }

    //创建执行的初始化的方法
    public void initMethod() {
        System.out.println("第三步 执行初始化方法");
    }

    public void destroyMethod(){
        System.out.println("第五步 执行销毁方法");
    }
}

Spring配置文件

    <bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手机"></property>
    </bean>

获取Bean对象

    @Test
    public void testBean3() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("第四步 获取创建bean实例对象");
        System.out.println(orders);

        //手动让bean实例销毁
        ((ClassPathXmlApplicationContext) context).close();
    }

在这里插入图片描述

如果添加了后置处理器,那么Bean的生命周期有七步

  1. 通过构造器创建 bean 实例(无参数构造)
  2. 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
  3. 把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
  4. 调用 bean 的初始化的方法(需要进行配置初始化的方法)
  5. 把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
  6. bean 可以使用了(对象获取到了)
  7. 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)


1、创建类,实现接口 BeanPostProcessor,创建后置处理器

public class MyBeanPost implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        return bean;
    }
}

2、在配置文件中配置了后置处理器,那么会为在配置文件中所有bean都添加后置处理器

    <bean id="orders" class="com.study.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手机"></property>
    </bean>

    <!--配置后置处理器-->
    <bean id="myBeanPost" class="com.study.spring5.bean.MyBeanPost"></bean>

在这里插入图片描述

自动装配

1、什么是自动装配
(1)根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入

emp

public class Emp {
    private Dept dept;

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

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
    <!--实现自动装配
    bean标签属性autowire,配置自动装配
    autowire属性常用两个值:
                byName根据属性名称注入,注入值bean的id值和类属性名称一样
                byType根据属性类型注入
    -->
    <bean id="emp" class="com.study.spring5.autowire.Emp" autowire="byName"></bean>
    
    <bean id="dept" class="com.study.spring5.autowire.Dept"></bean>

使用byType,相同类型不能定义多个,否则 报错(根据类型找配置文件中的对象,配置文件配置多个对象,就会造成无法确定是那个对象)
在这里插入图片描述

引入外部属性文件

当一个对象要配置的属性很多时,就可以通过引入外部属性来进来配置

以数据库连接池为例

先引入jar包
在这里插入图片描述

1、引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties 格式文件,写数据库信息

jdbc.properties
在这里插入图片描述

2、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">

<!--加入-->
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

3、在Spring配置文件中 配置连接池

    <!--配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClass}" />
        <property name="url" value="${prop.url}" />
        <property name="username" value="${prop.username}" />
        <property name="password" value="${prop.password}" />
    </bean>

IOC操作 Bean管理(基于注解方式)

创建对象

(1)@Component:普通组件
(2)@Service:一般用于业务逻辑层或service层上
(3)@Controller:一般用于web层
(4)@Repository:一般用于dao层

上面四个注解功能是一样的,都可以用来创建 bean 实例


1、引入aop依赖
在这里插入图片描述

2、开启组件扫描

添加名称空间 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:p="http://www.springframework.org/schema/p"
       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">

开启组件扫描

    <!--开启组件扫描
        base-package: 要扫描那个包
        1 如果扫描多个包,多个包使用逗号隔开
        2 扫描包上层目录(多个注解类在同一个包下)
    -->
    <context:component-scan base-package="com.study.spring5"></context:component-scan>

3、创建类,在类上面添加创建对象注解

//@Component(value = "userService") 等同于 <bean id="userService" class="com.study.spring5.service.UserService"></bean>
//注解后面的 values 是设置 id
//class 不需要指定,因为开启组件扫描,Spring扫描到这,发现是bean,自然会得到这个类的全路径

//在注解里面value属性值可以省略不写,
//默认值是类名称,首字母小写
//UserService -- userService
@Component(value = "userService")
public class UserService {
    public void add() {
        System.out.println("UserService调用了add.......");
    }
}

测试

    @Test
    public void addTest() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }

在这里插入图片描述

组件扫描细节配置

    <!-- 实例1
        use-default-filters: 表示不使用默认filter,而使用自己配置filter
        context:include-filter: 配置规则(设置扫描那些内容)
        type="annotation": 类型为注解
        expression="org.springframework.stereotype.Controller": 表示扫描类型为Controller的注解
        整体意思: 只扫描在com.study包下的 注解类型为 Controller 的 类
    -->
    <context:component-scan base-package="com.study" use-default-filters="false">
        <context:include-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>



    <!--实例2
        context:exclude-filter type="annotation": 设置不包含那些注解
        整体意思: 扫描com.study包下 不包含 Controller 的 所有注解
    -->
    <context:component-scan base-package="com.study">
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

基于注解方式实现属性注入

@Autowired:根据属性类型进行自动装配

1、把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解

UserService

@Service
public class UserService {
    public void add() {
        System.out.println("UserService调用了add.......");
        userDao.add();
    }
}

UserDaoImpl

@Repository
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("dao add.........");
    }
}


2、在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解

@Service
public class UserService {

    //定义dao类型属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired //根据类型注入
    private UserDao userDao;

    public void add() {
        System.out.println("UserService调用了add.......");
        userDao.add();
    }
}


测试
在这里插入图片描述


@Qualifier:根据名称进行注入
这个@Qualifier 注解的使用,和上面@Autowired一起使用

@Autowired 是根据 属性类型来注入,但如果有多个相同类型的bean,使用这个注解就麻烦了,比如接口的实现类
因此,使用 @Qualifier 通过名称(注解设置的 value) 就可以很好的解决这个问题

UserDaoImpl

//默认的value是 类的名称(第一个字母小写)
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("dao add.........");
    }
}

UserService

@Service
public class UserService {

    //定义dao类型属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired //根据类型注入
    @Qualifier(value = "userDaoImpl1") //指定value
    private UserDao userDao;

@Resource:可以根据类型注入,可以根据名称注入
类型注入

    @Resource
    private UserDao userDao;

名称注入

    @Resource(name = "userDaoImpl1")
    private UserDao userDao;


@Value:注入普通类型属性

    @Value("张三")
    private String name;

完全注解开发

1、创建配置类,替代 xml 配置文件

SpringConfig

@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = "com.study.spring5")
public class SpringConfig {

}

UserService

@Service
public class UserService {

    @Value("张三")
    private String name;

    @Resource(name = "userDaoImpl1")
    private UserDao userDao;

    public void add() {
        System.out.println("UserService调用了add.......");
        userDao.add();
    }
}

测试

    @Test
    public void TestService() {
        //加载配置类
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值