Spring学习(三)-Bean的种类,作用域,生命周期

一、Bean的种类

1.1、种类介绍

Spring 中有两种类型的 Bean, 一种是普通Bean, 另一种是工厂Bean, 即FactoryBean.

工厂 Bean 跟普通Bean不同, 其返回的对象不是指定类的一个实例, 其返回的是该工厂 Bean 的 getObject 方法所返回的对象

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

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

image

1.2、FactoryBean实现

1)创建类,让这个类作为工厂 bean,实现接口 FactoryBean

package com.dianchou.spring.bean;

import com.dianchou.spring.dao.Course;
import org.springframework.beans.factory.FactoryBean;

/**
 * @author lawrence
 * @create 2020-07-07 16:29
 */
public class MyBean implements FactoryBean<Course> {

    //定义返回 bean
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setName("Math");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

2)spring配置文件配置

<bean id="myBean" class="com.dianchou.spring.bean.MyBean"></bean>

3)测试

@Test
public void testMyBean(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("bean3.xml");
    Course course = ctx.getBean("myBean", Course.class);
    System.out.println(course);
}
image

二、Bean作用域

1)在 Spring 中, 可以在 <bean> 元素的 scope 属性里设置 Bean 的作用域.

2)默认情况下, Spring 只为每个在 IOC 容器里声明的 Bean 创建唯一一个实例, 整个 IOC 容器范围内都能共享该实例:所有后续的 getBean() 调用和 Bean 引用都将返回这个唯一的 Bean 实例.该作用域被称为 singleton, 它是所有 Bean 的默认作用域

image

3)singleton 和 prototype 区别

①singleton 单实例,prototype 多实例

②设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象 ;设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用 getBean 方法时候创建多实例对象

三、Bean生命周期

3.1、生命周期

从对象创建到对象销毁的过程

3.2、bean 生命周期

(1)通过构造器创建 bean 实例(无参数构造)

(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)

(3)调用 bean 的初始化的方法(需要进行配置初始化的方法)

(4)bean 可以使用了(对象获取到了)

(5)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

3.3、生命周期演示

1)创建实体类

package com.dianchou.spring.bean;

/**
 * @author lawrence
 * @create 2020-07-07 17:18
 */
public class Person {
    private String Name;

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

    public void setName(String name) {
        Name = name;
        System.out.println("第二步: 调用set方法设置属性值");
    }

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

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

2)spring配置文件

<bean id="person" class="com.dianchou.spring.bean.Person" init-method="initMethod" destroy-method="destroyMethod">
    <property name="name" value="lawrence"></property>
</bean>

3)测试

@Test
public void testBean() {
    // ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    Person person = context.getBean("person", Person.class);
    System.out.println("第四步 获取创建 bean 实例对象");
    System.out.println(person);
    //手动让 bean 实例销毁
    context.close();
}
image

3.4、Bean的后置处理器

Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理.

Bean 后置处理器对 IOC 容器里的所有 Bean 实例逐一处理, 而非单一实例. 其典型应用是: 检查 Bean 属性的正确性或根据特定的标准更改 Bean 的属性.

对Bean 后置处理器而言, 需要实现接口BeanPostProcessor. 在初始化方法被调用前后, Spring 将把每个 Bean 实例分别传递给上述接口的以下两个方法:

image

bean 的后置处理器,bean 生命周期有七步

(1)通过构造器创建 bean 实例(无参数构造)

(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)

(3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization

(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)

(5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization

(6)bean 可以使用了(对象获取到了)

(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

实例演示:

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

package com.dianchou.spring.bean;

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

/**
 * @author lawrence
 * @create 2020-07-07 17:46
 */
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)spring配置文件

<bean id="myBeanPost" class="com.dianchou.spring.bean.MyBeanPost"></bean>

<bean id="person" class="com.dianchou.spring.bean.Person" init-method="initMethod" destroy-method="destroyMethod">
    <property name="name" value="lawrence"></property>
</bean>

3)测试

@Test
public void testBean() {
    // ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    Person person = context.getBean("person", Person.class);
    System.out.println("第四步 获取创建 bean 实例对象");
    System.out.println(person);
    //手动让 bean 实例销毁
    context.close();
}

image

四、Bean的自动装配

4.1、什么是自动装配

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

4.2、示例

1)根据属性名称自动注入

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

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

2)根据属性类型自动注入

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

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

五、外部属性文件引入(如jdbc)

1)引入相关jar包

image

2)创建外部属性文件,properties 格式文件,写数据库信息

prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/mybatis
prop.userName=root
prop.password=123456

3)把外部 properties 属性文件引入到 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: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 http://www.springframework.org/schema/util/spring-util.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


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

    <!--配置连接池-->
    <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>

4)测试

@Test
public void testDataSource() throws SQLException {
    ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
    DruidDataSource dataSource = context.getBean("dataSource", DruidDataSource.class);
    System.out.println(dataSource.getConnection());
    System.out.println(dataSource.getDriverClassName());
}

image

原文地址:https://www.cnblogs.com/hujinzhong/p/13261567.html