SpringIOC方面知识

1.Spring的框架了解

在这里插入图片描述
Spring框架采用的是分层架构,它分为了20多个模块,主要有图上几个核心模块。这些模块大体分为

1.Core Container(核心容器)模块:核心容器模块是其他模块建立的基础。有Beans、Core、Context、Context-support模块和SpEL模块。
Beans模块:提供了BeanFactory接口,这个是工厂模式的经典实现,是基础类型的IOC容器,它是管理Bean的工厂,主要负责初始化各种Bean,然后调用bean的生命周期。BeanFactory是多例对象使用,构建核心容器时,采用延迟加载的方式,但是这种模式在开发中不常用。开发中用它的子接口ApplicationContext来获取核心容器对象

BeanFactory beanFactory=new XmlBeanFactory(new ClassPathResource("bean.xml"));

Core模块:是Spring框架的核心工具,Spring其他组件都需要用到这个包里的类。提供的spring框架基本组成部分,包括IoC和DI功能。

–Context模块:它是建立在Core和Beans模块的基础上,其中包含ApplicationContext接口,被称为上下文模块的焦点。这个ApplicationContext接口是BeanFactory的子接口,一般我们用这种模式来获取核心容器对象(前提是容器中已经注入bean对象,所以ApplicationContext在初始化时会自检依赖属性是否注入)。这种模式适合单例对象,采用立即加载的方式获得配置bean对象

ApplicationContext的3个常用实现类:

(1)通过ClassPathXmlApplicationContext创建

ClassPathXmlApplicationContext会从类路径classPath中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作,其使用语法如下。

ApplicationContext applicationContext =new ClassPathXmlApplicationContext("bean.xml")

(2).通过FileSystemXmlApplicationContext创建

FileSystemXmlApplicationContext会从指定的文件系统路径(绝对路径)中寻找指定的XML配置文件,找到并装载完成ApplicationContext的实例化工作,其使用语法如下。

ApplicationContext applicationContext =new FileSystemXmlApplicationContext("D:/workspaces/bean.xml")

(3) AnnotationConfigApplicationContext(注解)创建

ApplicationContext applicationContext =new AnnotationConfigApplicationContext(SpringConfiguration.class);

–Context-support模块:提供第三方库嵌入Spring的集成支持,比如缓存,邮件发送(JavaMail),任务调度等。

–SpEL模块:一种表达式语言。

BeanFactory和ApplicationContext区别

BeanFactory和ApplicationContext两种容器都是通过XML配置文件加载Bean的。二者的主要区别在于,如果Bean的某一个属性没有注入,使用BeanFacotry加载后,在第一次调用getBean()方法时会抛出异常,而ApplicationContext则在初始化时自检,这样有利于检查所依赖属性是否注入。因此,在实际开发中,通常都优先选择使用ApplicationContext,而只有在系统资源较少时,才考虑使用BeanFactory。

2.Data Access/Integration数据访问/集成模块

这里面常用的模块有以下3个

–JDBC模块:提供了一个JDBC的抽象层,大幅度地减少了在开发过程中对数据库操作的编码;

–ORM模块:对流行的对象关系映射API,包括JPA、JDO和Hibernate提供了集成层支持。

–Transactions事务模块:支持对实现特殊接口以及所有POJO类的编程和声明式的事务管理。

3.Web:Spring的Web层包括WebSocket、Servlet、Web和Portlet模块

–Servlet模块:也称为Spring-webmvc模块,包含了Spring的模型(model)—视图(view)—控制器(controller)(MVC)和REST Web Services实现的Web应用程序。

–Web模块:提供了基本的Web开发集成特性,例如:多文件上传功能、使用Servlet监听器来初始化IoC容器以及Web应用上下文。

4.AOP(面向切面编程):提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。

5.Instrumentation(工具):提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。

6.Messaging(消息):Spring 4.0以后新增的模块,它提供了对消息传递体系结构和协议的支持。

7.Test(测试):提供了对单元测试和集成测试的支持


2. Spring IOC和依赖注入(DI)

依赖注入(DI)与控制反转(IOC)的含义相同,只不过从不同的角度来描述同一个概念。

1.IOC:

控制反转是一种思想。以往某个Java对象(调用者)需要调用另一个java对象时(被调用者,即被依赖对象),调用者通常采用"new 被调用者"的代码来创建对象,这种方式耦合性太高,还有就是Service底层存在很多构造器,每一次调用都new对象,会太繁琐。
在这里插入图片描述
而在使用Spring框架后,对象的实例不再由调用者来创建,而是由Spring容器来创建。Spring容器会负责控制程序之间的关系,不再是调用者的程序代码直接控制,它像一个工厂一样管理很多的bean对象,这样控制权就由new程序代码转移到了Spring容器。

2.依赖注入(DI)

Spring容器负责将被依赖对象(被调用者)赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入。实际就是控制反转(IOC)思想。
在这里插入图片描述

3.Bean的装配方式/依赖注入 (实例化后,注入Bean中所有属性值)

Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配等(其中最常用的是基于注解的装配)

3.1 基于XML的装配(setter和构造方法)

(1) 构造函数注入:这种方式要求待注入的对象中,这个bean类包含有参构造方法,它会调用有参构造方法来注入,而且还要在bean.xml中注入这些参数属性,否则不注入参数属性(它就会默认调用无参构造方法,这显然会报错)。

在这里插入图片描述

//注入有参构造方法的参数属性
<bean id="accountService" class="com.jh.service.impl.AccountServiceImpl">
        <constructor-arg name="name" value="张三"></constructor-arg>
        <constructor-arg name="age" value="23"></constructor-arg>
        <constructor-arg name="birthday" ref="date"></constructor-arg>
 </bean>
    
    <!--配置一个日期对象-->
    <bean id="date" class="java.util.Date"></bean>      

(2) 以属性setter方法注入:在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求。

· Bean类必须提供一个默认的无参构造方法首先实例化bean(实例化就是创建bean)。

· Bean类必须为需要注入的属性提供对应的setter方法。

从settet方法看出依赖注入是在bean实例化之后的

在这里插入图片描述

<bean id="accountService2" class="com.jh.service.impl.AccountServiceImpl2">
        <property name="name" value="李四"></property>
        <property name="age" value="21"></property>
        <property name="birthday" ref="date"></property>
    </bean>
   
    <!--配置一个日期对象-->
    <bean id="date" class="java.util.Date"></bean> 

3.2 基于注解(Annotation)的装配

Spring中定义了一系列的注解,常用的注解如下所示。

  • @Component:可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。
  • @Repository:用于将数据访问层(DAO层)的类标识为Spring中的Bean,其功能与@Component相同
  • @Service:通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同。
  • @Controller:通常作用在控制层(如Spring MVC的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。
  • @Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。
  • @Resource:其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。
  • @Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。
  • @Value:以${}注入属性

3.3 自动装配(bean.xml中的autowire属性)

Spring的元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。所谓自动装配,就是将一个Bean自动地注入到其他Bean的Property中。
在这里插入图片描述
在这里插入图片描述
上述配置文件中,用于配置userService和userController的元素中除了id和class属性外,还增加了autowire属性,并将其属性值设置为byName。在默认情况下,配置文件中需要通过ref来装配Bean,但设置了autowire="byName"后,Spring会自动寻找userService Bean中的属性,并将其属性名称与配置文件中定义的Bean做匹配。

4.bean的3种实例化方式(实例化就是创建bean对象,默认无参构造器创建)

在面向对象的程序中,我们要使用一个对象及成员属性,首先得实例化对象,Spring容器也不例外,也需要实例化bean对象,才能使用它,依赖注入都是在bean对象实例化后才能去注入,下面提供三种实例化bean的方式。

//要实例化的bean对象
public class AccountServiceImpl implements IAccountService {
    public AccountServiceImpl(){
        System.out.println("对象创建了");
    }
}

第一种:通过调用无参构造器来实例化bean对象,这也是Spring默认使用的实例化bean的方式,默认调用无参构造方法。

首先定义了配置文件的路径,然后Spring容器ApplicationContext会加载配置文件。在加载时,Spring容器会通过id为accountService的实现类AccountServiceImpl中默认的无参构造方法对Bean进行实例化.

//bean.xml
<bean id="accountService" class="com.jh.service.impl.AccountServiceImpl"></bean>

//创建测试类看是否实例化bean
     public static void main(String[] args) {
        //--------ApplicationContext 立即加载----------------------
        //1.获取核心容器对象
        //ApplicationContext ac= new ClassPathXmlApplicationContext("bean.xml");
        ClassPathXmlApplicationContext ac= new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取Bean对象
        IAccountService as= (IAccountService)ac.getBean("accountService");
        System.out.println(as);//com.jh.service.impl.AccountServiceImpl@1dd92fe2
        as.saveAccount();
        //手动关闭容器
        ac.close();
        }

第二种:通过静态工厂实例化bean

//bean.xml
<bean id="accountService" class="com.jh.factory.StaticFactory" factory-method="getAccountService"></bean>

/*
使用静态工厂是实例化Bean的另一种方式。该方式要求开发者创建一个静态工厂的方法来创建Bean的实例,其Bean配置中的class属性所指定的不再是Bean实例的实现类,而是静态工厂类,同时还需要使用factory-method属性来指定所创建的静态工厂方法。下面通过一个案例来演示如何使用静态工厂方式实例化Bean。
*/
public class StaticFactory {
    public static IAccountService getAccountService(){
        //静态工厂通过返回一个实例对象new AccountServiceImpl()来实例化
        return new AccountServiceImpl();
    }
}

//测试类同上面

第三种:通过普通成员工厂实例化bean

//bean.xml
<bean id="instanceFactory" class="com.jh.factory.InstanceFactory"></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>

/*
还有一种实例化Bean的方式就是采用实例工厂。此种方式的工厂类中,不再使用静态方法创建Bean实例,而是采用直接创建Bean实例的方式。同时,在配置文件中,需要实例化的Bean也不是通过class属性直接指向的实例化类,而是通过factory-bean属性指向配置的实例工厂,然后使用factory-method属性确定使用工厂中的哪个方法。下面通过一个案例来演示实例工厂方式的使用。
*/
public class InstanceFactory {
    public IAccountService getAccountService(){
        //也是通过返回一个实例化对象new AccountServiceImpl()来实例化
        return new AccountServiceImpl();
    }
    
//测试同上面

5.bean的作用域和生命周期

1.)5个作用域:img

常用的还是单例singleton、多例prototype。singleton是单例模型:Spring容器创建时,它就会自动调用默认的无参构造器实例化bean(实例化bean就是创建bean对象),不管我们有没有使用,它都存在,每次获取的bean对象都是同一个对象,就和对象内存地址一样的对象。prototype:是多例模型,当创建Spring容器时,并不会立即实例化创建bean对象,而是当需要获取bean对象时才去实例化bean,是一种懒汉式,所以它们每一次创建的bean都不是同一个对象。

五种作用域中,request、session和global session三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。


2)bean的生命周期

Spring容器可以管理singleton(单例模型)作用域的bean的生命周期,在单例模型下能够精确知道Bean何时被创建,何时被初始化,以及何时被销毁。
对于prototype作用域的bean,Spring只负责创建bean实例,当容器中有了bean实例后,它的生命周期都交由它的调用者管理,Spring容器不再跟踪其生命周期,每次调用者请求prototype作用域下的bean时,Spring容器都会创建一个新的实例bean对象,并且不会再管理bean的生命周期。你想一下,每次调用bean都重新创建bean对象,Spring要管理每一个bean生命周期就会很耗费时间,不如交由它的调用者管理。

下面是单例模型下的bean生命周期:
在这里插入图片描述
(1)根据配置情况调用Bean构造方法或工厂方法实例化Bean。(2)利用依赖注入完成Bean中所有属性值的配置注入。

(3)如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的id值。

(4)如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory()方法传入当前工厂实例的引用。

(5)如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext()方法传入当前ApplicationContext实例的引用。

(6)如果BeanPostProcessor和Bean关联,则Spring将调用该接口的预初始化方法postProcessBeforeInitialzation()对Bean进行加工操作,这个非常重要,Spring的AOP就是用它实现的。

(7)如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法。

(8)如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化方法。

(9)如果有BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfterInitialization()。此时,Bean已经可以被应用系统使用了。

(10)如果在 中指定了该Bean的作用范围为scope=“singleton”,则将该Bean放入Spring IoC的缓存池中,将触发Spring对该Bean的生命周期管理;如果在中指定了该Bean的作用范围为scope=“prototype”,则将该Bean交给调用者,调用者管理该Bean的生命周期,Spring不再管理该Bean。

(11)如果Bean实现了DisposableBean接口,则Spring会调用destory()方法将Spring中的Bean销毁;如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则Spring将调用该方法进行销毁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值