[模块二]Spring IOC应用

Posted cn-zhou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模块二]Spring IOC应用相关的知识,希望对你有一定的参考价值。

【1】Spring IOC 基础

文件名 说明
beans.xml 定义需要实例化对象的类的全限定类名以及类之间依赖关系描述。
BeanFactory.java 通过反射技术来实例化对象并维护对象之间的依赖关系。

Spring框架的IOC实现(3种):

  1. 纯xml(bean信息定义全部配置在xml中):

    // JavaSE应用
    // 方式一
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
    // 方式二
    new FileSystemXmlApplicationContext("c:/beans.xml");
    
    // JavaWeb应用
    ContextLoaderListener(监听器去加载xml)
    
  2. xml+注解(部分bean使用xml定义,bean使用注解定义)

    // JavaSE应用
    // 方式一
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
    // 方式二
    new FileSystemXmlApplicationContext("c:/beans.xml");
    
    // JavaWeb应用
    ContextLoaderListener(监听器去加载xml)
    
  3. 纯注解(所有的bean都是用注解定义)

    // JavaSE应用
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    
    // JavaWeb应用
    ContextLoaderListener(监听器去加载注解配置类)
    

1.1 BeanFactory与ApplicationContext区别

名称 说明
BeanFactory Spring框架中IOC容器的顶层接口,只是用来定义一些基础功能和基础规范。
ApplicationContext 是BeanFactory的一个子接口,具备BeanFactory提供的全部功能。
  1. 两个实现类基于xml配置:

    • ClassPathXmlApplicationContext
    • FileSystemXmlApplicationContext
  2. 基于注解配置的实现类:

    • AnnotationConfigApplicationContext
  3. 启动IOC容器的方式

    • Java环境下启动IOC容器

      • ClassPathXmlApplicationContext:从类的根路径下加载配置文件(推荐使用)
      • FileSystemXmlApplicationContext:从磁盘路径上加载配置文件
      • AnnotationConfigApplicationContext:纯注解模式下启动Spring容器
    • Web环境下启动IOC容器

      • 从xml启动容器

        <!DOCTYPE web-app PUBLIC
             "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
             "http://java.sun.com/dtd/web-app_2_3.dtd" >
        <web-app>
            <display-name>Archetype Created Web Application</display-name>
            <!--配置Spring ioc容器的配置?件-->
            <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:applicationContext.xml</param-value>
            </context-param>
            <!--使?监听器启动Spring的IOC容器-->
            <listener>
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            </listener>
        </web-app>
        
      • 从配置类启动容器

        <!DOCTYPE web-app PUBLIC
                      "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
                 "http://java.sun.com/dtd/web-app_2_3.dtd" >
        <web-app>
            <display-name>Archetype Created Web Application</display-name>
            <!--告诉ContextloaderListener知道我们使?注解的?式启动ioc容器-->
            <context-param>
                <param-name>contextClass</param-name>
                <param-value>org.springframework.web.context.support.AnnotationConfigWebAppli
                    cationContext</param-value>
            </context-param>
            <!--配置启动类的全限定类名-->
            <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>com.lagou.edu.SpringConfig</param-value>
            </context-param>
            <!--使?监听器启动Spring的IOC容器-->
            <listener>
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            </listener>
        </web-app>
        

1.2 纯XML模式

1.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
 https://www.springframework.org/schema/beans/spring-beans.xsd">

2.实例化Bean的三种方式

  • 方式一:使用无参构造函数

    在默认情况下,它会通过反射调??参构造函数来创建对象。如果类中没有?参构造函数,将创建失败。

    <!--配置service对象-->
    <bean id="userService" class="com.lagou.service.impl.TransferServiceImpl"></bean>
    
  • 方式二:使用静态方法创建

    在实际开发中,我们使?的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创建的过程 中会做很多额外的操作此时会提供?个创建对象的?法,恰好这个?法是static修饰的?法,即是此种情况。

    <!--使?静态?法创建对象的配置?式-->
    <bean id="userService" class="com.lagou.factory.BeanFactory"factory-method="getTransferService"></bean>
    
  • 方式三:使用实例化方法创建

    此种?式和上?静态?法创建其实类似,区别是?于获取对象的?法不再是static修饰的了,?是类中的?个普通?法。此种?式?静态?法创建的使??率要??些。

    <!--使?实例?法创建对象的配置?式-->
    <bean id="beanFactory" class="com.lagou.factory.instancemethod.BeanFactory"></bean>
    <bean id="transferService" factory-bean="beanFactory" factory-method="getTransferService"></bean>
    

3.Bean的X及生命周期

  • 作用范围的改变
    • 单例模式[singleton](默认):生命周期与容器相同。
    • 多例模式[prototype]:spring框架只负责创建,不负责销毁。

4.Bean的标签属性

属性名称 说明
id ?于给bean提供?个唯?标识。在?个标签内部,标识必须唯?。
class ?于指定创建Bean对象的全限定类名。
name ?于给bean提供?个或多个名称。多个名称?空格分隔。
factory-bean ?于指定创建当前bean对象的??bean的唯?标识。当指定了此属性之后,class属性失效。
factory-method ?于指定创建当前bean对象的???法,如配合factory-bean属性使?,则class属性失效。如配合class属性使?,则?法必须是static的。
scope ?于指定bean对象的作?范围。通常情况下就是singleton。当要?到多例模式时,可以配置为prototype。
init-method ?于指定bean对象的初始化?法,此?法会在bean对象装配后调?。必须是?个?参?法。
destroy-method ?于指定bean对象的销毁?法,此?法会在bean对象销毁前执?。它只能为scope是singleton时起作?。

5.DI依赖注入的xml配置

  • 依赖注入分类

    • 按照注入的方式分类

      类别 说明
      构造函数注入 顾名思义,就是利?带参构造函数实现对类成员的数据赋值。
      set方法注入 它是通过类成员的set?法实现数据的注?。(使?最多的)
    • 按照注入的数据类型分类

      类别 说明
      基本类型和String 注?的数据类型是基本类型或者是字符串类型的数据。
      其他Bean类型 注?的数据类型是对象类型,称为其他Bean的原因是,这个对象是要求出现在IoC容器中的。那么针对当前Bean来说,就是其他Bean了。
      复杂类型(集合类型) 注?的数据类型是Aarry,List,Set,Map,Properties中的?种类型。
  • 依赖注入的配置实现之构造函数注入

    • 顾名思义,就是利?构造函数实现对类成员的赋值。它的使?要求是,类中提供的构造函数参数个数必须和配置的参数个数?致,且数据类型匹配。同时需要注意的是,当没有?参构造时,则必须提供构造函数参数的注?,否则Spring框架会报错。

    • 在使用构造函数注入的时候,涉及的标签是constructor-arg,该标签有如下属性:

      属性名称 说明
      name ?于给构造函数中指定名称的参数赋值。
      index ?于给构造函数中指定索引位置的参数赋值。
      value ?于指定基本类型或者String类型的数据。
      ref ?于指定其他Bean类型的数据。写的是其他bean的唯?标识。
  • 依赖注入的配置实现之set方法注入

    • 顾名思义,就是利?字段的set?法实现赋值的注??式。此种?式在实际开发中是使?最多的注??式。

    • 在使用set方法注入时,需要使用property标签,该标签属性如下:

      属性名称 说明
      name 指定注?时调?的set?法名称。(注:不包含set这三个字?,druid连接池指定属性名称)
      value 指定注?的数据。它?持基本类型和String类型。
      ref 指定注?的数据。它?持其他bean类型。写的是其他bean的唯?标识。复杂类型数据,它指的是集合类型数据。集合分为两类,?类是List结构(数组结构),?类是Map接?(键值对)。

1.3 XML与注解相结合模式

注意点:

  1. 实际企业开发中,纯XML模式使用很少了;
  2. 引入注解功能不需要引入额外的jar;
  3. xml+注解结合模式,xml文件依然存在,所以,spring IOC容器的启动仍然从加载xml开始;
  4. 第三方jar中的bean定义在xml中,比如德鲁伊数据库连接池;自己开发的bean的定义使用注解。
  • xml中标签和注解的对应(IOC)

    xml形式 对应的注解形式
    标签 @Component("accountDao"),注解加在类上。bean的id属性内容直接配置在注解后?如果不配置,默认定义个这个bean的id为类的类名?字??写;另外,针对分层代码开发提供了@Componenet的三种别名@Controller、@Service、@Repository分别?于控制层类、服务层类、dao层类的bean定义,这四个注解的?法完全?样,只是为了更清晰的区分?已。
    标签的scope属性 @Scope("prototype"),默认单例,注解加在类上。
    标签的init-method属性 @PostConstruct,注解加在?法上,该?法就是初始化后调?的?法。
    标签的destroy-method属性 @PreDestory,注解加在?法上,该?法就是销毁前调?的?法。
  • DI依赖注入的注解实现方式

    • @Autowired(推荐使用)

      1. @Autowired为Spring提供的注解,需要导包;
      2. @Autowired采取的策略是按类型注入。当一个类型有多个bean值的时候,会造成无法选择具体注入哪一个的情况,这个时候就需要配合@Qualifier使用。@Qualifier告诉Spring具体装配哪个对象。这个时候我们就可以通过类型和名称定位到我们想注?的对象。
    • @Resource

      @Resource在jdk11中已经移除,如果使用要单独导入jar包。

      1. @Resource注解由J2EE提供,需要导入包;
      2. @Resource默认按照ByName自动注入。
        • 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到就抛出异常;
        • 如果指定了name,则从上下文中找到名称匹配的bean进行装配,找不到则抛出异常;
        • 如果指定了type,则从上下文找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
        • 如果既没有指定name,又没有指定type,则自动按照ByName方式进行装配。

1.4 纯注解模式

注解名 说明
@Confifiguration 表名当前类是?个配置类
@ComponentScan 替代 context:component-scan
@PropertySource 引?外部属性配置?件
@Import 引?其他配置类
@Value 对变量赋值,可以直接赋值,也可以使? ${} 读取资源配置?件中的信息
@Bean 将?法返回对象加? SpringIOC 容器

【2】Spring IOC高级特性

2.1 lazy-Init延迟加载

应用场景

  1. 开启延迟加载一定程度提高容器启动和运转性能;
  2. 对于不常使用的Bean设置延迟加载,这样偶尔使用的时候再加载,不必要从一开始该Bean就占用资源。

Bean的延迟加载(延迟创建)

原因:ApplicationContext容器的默认行为是在启动服务器时将所有singleton bean提前实例化。默认lazy-init=“false”。

2.2 FactoryBean和BeanFactory

名称 说明
FactoryBean BeanFactory接?是容器的顶级接?,定义了容器的?些基础?为,负责?产和管理Bean的?个??,具体使?它下?的?接?类型,?如ApplicationContext。
BeanFactory Spring中Bean有两种,?种是普通Bean,?种是??Bean(FactoryBean),FactoryBean可以?成某?个类型的Bean实例(返回给我们),也就是说我们可以借助于它?定义Bean的创建过程。

2.3 后置处理器

Spring提供了两种后处理bean的扩展接?,分别为 BeanPostProcessor 和BeanFactoryPostProcessor,两者在使?上是有所区别的。

接口名称 说明
BeanPostProcessor BeanPostProcessor是针对Bean级别的处理,可以针对某个具体的Bean.该接?提供了两个?法,分别在Bean的初始化?法前和初始化?法后执?,具体这个初始化?法指的是什么?法,类似我们在定义bean时,定义了init-method所指定的?法。定义?个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进?处理。如果要对具体的某个bean处理,可以通过?法参数判断,两个类型参数分别为Object和String,第?个参数是每个bean的实例,第?个参数是每个bean的name或者id属性的值。所以我们可以通过第?个参数,来判断我们将要处理的具体的bean。注意:处理是发?在Spring容器的实例化和依赖注?之后。
BeanFactoryPostProcessor BeanFactory级别的处理,是针对整个Bean的??进?处理,典型应?:PropertyPlaceholderConfifigurer,此接?只提供了?个?法,?法参数为ConfifigurableListableBeanFactory,该参数类型定义了?些?法。其中有个?法名为getBeanDefifinition的?法,我们可以根据此?法,找到我们定义bean的BeanDefifinition对象。然后我们可以对定义的属性进?修改,?法名字类似我们bean标签的属性,setBeanClassName对应bean标签中的class属性,所以当我们拿到BeanDefifinition对象时,我们可以?动修改bean标签中所定义的属性值。BeanDefifinition对象:我们在 XML 中定义的 bean标签,Spring 解析 bean 标签成为?个 JavaBean,这个JavaBean 就是 BeanDefifinition。注意:调? BeanFactoryPostProcessor ?法时,这时候bean还没有实例化,此时 bean 刚被解析成BeanDefifinition对象。

以上是关于[模块二]Spring IOC应用的主要内容,如果未能解决你的问题,请参考以下文章

String---IOC

String---IOC

spring浅析

Spring学习总结- IOC

SPRING源码解析-SPRING 核心-IOC

Spring入门之IoC