Spring框架(深入SpringIOC容器学习(二))

目录,更新ing,学习Java的点滴记录

  目录放在这里太长了,附目录链接大家可以自由选择查看--------Java学习目录

Spring知识

  一丶SpringIOC初步认识↓↓↓
第一篇---->初识Spring
  二丶SpringIOC深入↓↓↓
第二篇---->深入SpringIoC容器(一)
第三篇---->深入SpringIoC容器(二)
  三丶装配SpringBean↓↓↓
第四篇---->依赖注入的方式
第五篇---->基于xml装配Bean
第六篇---->基于注解装配Bean
第七篇---->Spring Bean之间的关系
第八篇---->SpringBean的作用域
第九篇---->Spring 加载属性(properties)文件
第十篇---->Spring表达式(SpEL)
第十一篇---->Spring在xml中配置组件扫描
  四丶面向切面编程↓↓↓
第十二篇—>认识SpringAOP及底层原理
第十三篇—>使用@AspectJ注解开发AOP
第十四篇—>使用xml配置开发AOP
  五丶Spring中数据库编程↓↓↓
第十五篇—>数据库编程JdbcTemplate
  六丶Spring事务管理↓↓↓
第十六篇—>Spring事务管理初识
第十七篇—>编程式事务和声明式事务
第十八篇—>事务ACID特性
第十九篇—>事务传播行为
第二十篇—>事务隔离级别

1.3 Spring IoC容器

1.3.1 简要介绍
  • Spring IOC容器可以容纳我们所开发的各种Bean,并且我们可以从中获取各种发布在SpringIOC容器里的Bean,并且通过描述可以得到它.
  • Spring通过一个配置文件描述Bean及Bean之间的依赖关系,利用Java语言的反射功能实例化Bean并建立Bean之间的依赖关系.SpringIOC容器在完整这些底层工作的基础上,还提供了Bean实例缓存,生命周期管理,Bean实例代理,资源装载等高级功能
1.3.2 容器设计及继承结构图
  • SpringIOC容器的设计主要是基于BeanFactory和ApplicationContext两个接口,其中ApplicationContext是BeanFactory的子接口之一,BeanFactory是SpringIOC容器所定义的最底层接口,而ApplicationContext是其高级接口之一,并且对BeanFactory功能做了很多扩展,绝大部分情况下,都会使用ApplicationContext作为SpringIOC容器.
  • BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者.
  • 这边网上找了一张超详细的继承结构的图(右键可以查看图像会清楚一些)
      在这里插入图片描述
1.3.3 BeanFactory说明
  • 在上面的继承结构图中,可以清楚看到BeanFactory位于设计的最底层,它提供了SpringIOC容器的最底层的设计,下面我们看一下源码
      在这里插入图片描述
  • 下面对该接口中一些重要方法进行解释
      1) getBean的多个方法用于获取配置给SpringIOC容器的Bean.从参数类型看可以是字符串,也可以是class类型,由于Class类型可以扩展接口也可以继承父类,所以在一定程度上会存在使用父类类型无法准确获得实例的异常,比如学生类,它有男学生和女学生两个子类,如果通过学生类的Class就无法得到具体的实例,因为容器无法判断到底要选用哪个实现类
      2) isSingleton用于判断是否为单例,如果判断为真,表示该Bean在容器中作为一个唯一单例存在.默认情况下,Spring会为Bean创建一个单例,isSingleton返回true
      3) isPrototype则相反,如果判断为真,意思是当你从容器中获取Bean,容器就为你生成了一个新的实例.默认情况下,isPrototype返回false
      4) 关于type的匹配,这是一个按Java类型匹配的方式
      5) getAliases方法是获取别名的方法
1.3.4 ApplicationContext说明
  • 为了扩展更多的功能,ApplicationContext接口扩展了许许多多的接口,它的功能非常强大.它有两个重要的实现类:ClassPathXmlApplicationContext:从 类路径下加载配置文件,FileSystemXmlApplicationContext: 从文件系统中加载配置文件
  • ClassPathXMLApplicationContext实现类之前已经用到很多次了,创建该实现类对象,并将全局配置文件作为参数进行传递,这样就能得到一个SpringIOC容器,再通过SpringIOC容器提供的方法拿到对应的bean对象执行相关操作就可以了
      在这里插入图片描述
  • 在这里插入图片描述
1.3.5 WebApplicationContext说明
  • 扩展于ApplicationContext,是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中装载配置文件完成初始化工作.从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象作为属性放在ServletContext中,以便于Web应用环境可以访问Spring应用上下文
  • 在这里插入图片描述
1.3.6 ConfigurableApplicationContext说明
  • 扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力

1.4 SpringIOC容器的初始化和依赖注入

  • SpringIOC容器的生成很复杂,但是了解SpringIOC容器的初始化过程还是不难理解的.Spring中Bean的初始化和依赖注入在SpringIOC容器中是两大步骤,先初始化才会进行依赖注入.
  • Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean之间的依赖关系,为上层应用提供准备就绪的运行环境,其中Bean缓存池使用HashMap实现
      在这里插入图片描述
  • Bean初始化的详细3步:
     1) Resource定位,这一步是SpringIOC容器根据开发者的配置,进行资源定位,在Spring开发中,通过xml或者注解都是十分常见的方式,定位的内容是由开发者提供的
     2) BeanDefinition的载入,这个过程就是Spring根据开发者的配置获取对应的POJO,用以生成对应实例的过程
     3) BeanDefinition的注册,将之间载入的POJO往SpringIOC容器中注册,这样,开发人员就可以通过描述从中得到SpringIOC容器的Bean了.
  • 完成了上面的步骤,Bean就在SpringIOC容器中得到了初始化,但是没有完成依赖注入.也就是说没有注入其配置的资源给Bean,它现在还不能使用.对于依赖注入,SpringBean还有一个配置选项—lazy-init,其含义就是是否初始化SpringBean.在没有任何配置的情况下,它默认值为default,实际值为false,也就是SpringIOC默认会自动初始化Bean.如果将其设置为true,那么只有当我们使用SpringIOC容器的getBean方法获取Bean实例的时候,它才会进行初始化,完成依赖注入.
      在这里插入图片描述
  • 关于依赖注入的详细内容放在第二部分中说明

1.5 SpringBean的生命周期

  1. SpringIOC容器的本质目的是为了管理Bean.对于Bean而言,在容器中存在其生命周期,它的初始化和销毁也需要一个过程,在一些需要自定义的过程中,我们可以插入代码去改变他们的一些行为,以满足特定的需求,这就需要了解SpringBean的生命周期的知识了
  2. 生命周期主要是为了了解SpringIOC容器初始化和销毁Bean的过程,熟悉整个生命周期可以方便我们在初始化和销毁的特定流程中加入自定义方法,满足特定需求
  3. 详细过程图
      在这里插入图片描述
  4. 生命周期步骤文字说明
      1) 初始化:创建了一个SpringIOC容器的对象,默认作用域为单例
      2) 依赖注入(下一章节详细讲):按照Spring上下文对实例化的Bean进行配置,这里使用setter进行注入
      3) 如果Bean实现了接口BeanNameAware的setBeanName方法,那么此时就会调用这个方法
      4) 如果Bean实现了接口BeanFactoryAware的setBeanFactory方法,那么此时就会调用这个方法
      5) 如果Bean实现了接口ApplicationContextAware的setApplicationContext方法,并且SpringIOC容器对象也必须是一个ApplicationContext接口的实现类,那么才会调用这个方法,否则不调用
      6) 如果Bean实现了接口BeanPostProcessor接口的postProcessBeforeInitialization方法,那么此时会调用
      7) 如果Bean实现了接口InitializingBean的afterPropertiesSet方法,那么此时会调用
      8) 如果Bean自定义初始化方法,并且在Bean的配置文件中使用init-method进行了指定,那么会被调用
      9) 如果Bean实现了接口BeanPostProcessor接口的postProcessAfterInitialization方法,完成了到此的调用,这时候Bean就完成了初始化,那么Bean就生存在SpringIOC容器中了,我们就可以容器中获取对象了
      10) 如果服务器正常关闭,或者遇到其他关闭SpringIOC容器的调用,就会调用对应方法完成Bean的销毁,步骤为11,12
      11) 如果Bean实现了接口DisposableBean的destroy方法,那就会调用
      12) 如果Bean自定义了销毁方法,并且在Bean配置文件中使用destroy-method进行了指定,那么就会被调用
  5. 示例代码,了解生命周期过程
      特别说明:请仔细看上面的生命周期图,大部分接口是针对单个Bean而言的,而BeanPostProcessor接口是针对所有Bean而言,接口DisposableBean是针对SpringIOC容器本身,因此在后面代码中,我将这两个接口单独创建了实现类,我们只需要在SpringIOC容器中(配置文件)以bean的形式进行配置,SpringIOC容器就会自动识别.
      1) BeanPostProcessor实现类\
package com.spring.two;

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

public class BeanPostProcessorImpl implements BeanPostProcessor {

    // BeanPostProcessor接口中的方法
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【" + bean.getClass().getSimpleName() + "】调用BeanPostProcessor接口中的postProcessBeforeInitialization方法,对象" + beanName + "开始实例化");
        return bean;
    }

    // BeanPostProcessor接口中的方法
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【" + bean.getClass().getSimpleName() + "】调用BeanPostProcessor接口中的postProcessAfterInitialization方法,对象" + beanName + "实例化完成");
        return bean;
    }

}

  2) DisposableBean实现类

package com.spring.two;

import org.springframework.beans.factory.DisposableBean;

public class DisposableBeanImpl implements DisposableBean {

	//DisposableBean接口的destroy方法
	@Override
	public void destroy() throws Exception {
		System.out.println("调用接口DisposableBean的destroy方法");
	}

}

  3) Person–一个Bean类

package com.spring.two;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Person implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean{
	private String name = null;
	private int id;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		System.out.println("【Setter】为Person类的name属性赋值");
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		System.out.println("【Setter】为Person类的id属性赋值");
		this.id = id;
	}

	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + '\'' +
				", id=" + id +
				'}';
	}
	//自定义初始化方法
	public void myinit() {
		System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义初始化方法");
	}

	//自定义销毁方法
	public void mydestroy() {
		System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义销毁方法");
	}

	//BeanNameAware接口中方法
	@Override
	public void setBeanName(String arg0) {
		System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanNameAware接口的setBeanName方法");

	}

	//BeanFactoryAware接口中方法
	@Override
	public void setBeanFactory(BeanFactory arg0) throws BeansException {
		System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanFactoryAware接口的setBeanFactory方法");
	}

	//ApplicationContextAware接口中方法
	//特别强调,必须使用ApplicationContext及其实现类来创建SpringIOC容器,否则即便实现了该方法也不会调用
	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		System.out.println(
				"【" + this.getClass().getSimpleName() + "】调用ApplicationContextAware接口的setApplicationContext方法");
	}

	//InitializingBean接口中方法
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("【" + this.getClass().getSimpleName() + "】调用InitializingBean接口的afterPropertiesSet方法");
	}
}

  4) 全局配置文件applicationContext.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-4.0.xsd">

    <!--BeanPostProcessor定义 该接口是针对所有Bean而言的 -->
    <bean id="beanPostProcessor" class="com.spring.two.BeanPostProcessorImpl"/>
    <!--DisposableBean定义 该接口是针对SpringIOC容器本身的-->
    <bean id="disposableBean" class="com.spring.two.DisposableBeanImpl"/>

    <!--  自定义bean类,通过init-method,destroy-method指定自定义初始化方法和自定义销毁方法  -->
    <bean id="person" class="com.spring.two.Person"
          destroy-method="mydestroy" init-method="myinit">
        <property name="name" value="root"/>
        <property name="id" value="1"/>
    </bean>
</beans>


  5) 测试类

package com.spring.two;

import com.spring.one.JuiceMaker;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Test {
    public static void main(String[] args) {
        // 1. 获取SpringIOC容器,这里使用ClassPathXmlApplicationContext来接收
        // 原因是该实现类中含有close方法,在手动关闭时,可以调用生命周期中的销毁方法
        ClassPathXmlApplicationContext ctx =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        // 2. 获取Bean实例
        Person person =ctx.getBean(Person.class);
        // 3. 输出Bean对象
        System.out.println("【生命周期内】"+person);
        // 4. 关闭IOC容器,调用销毁方法
        ctx.close();
    }
}

  6) 测试结果
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值