微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

[模块二]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 factorybeanbeanfactory

名称 说明
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对象。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。