Spring系列之——IOC

什么是Ioc?

Ioc(控制反转),见名知意Ioc就是控制反转,那么控制的是什么?而又反转了什么?既然有反转原来又是怎样的?
A1:原来的程序是怎样的?
如果A类依赖B那么我们要创建一个A类的对象,就需要学会创建B然后在创建A的代码中创建B如下代码:

Public class Test{
Public static void main(String[] args){
A a=new A();
a.setb(new B);
} 

所有我们自己将要完成A和B的两个类的创建。
A2:控制的是什么?
这里我们控制的其实就是对象的创建,原来我们需要自己去控制对象的创建,比如我们的类作用就是创建一桶泡面但是,泡面中包含类调料包,它其实也是一个单独的类,那我们就要学会创建调料包,但事实上这是没有必要的。
A3:反转了什么?
如上所讲我们不需要去创建调料包那就不去,我们通过一个容器让会创建调料包的人去创建调料包,然后在通过java的反射机制获取调料包对象的一切信息,在动态的改变我们创建的方便面对象的信息完成依赖注入,从而得到一个完整的方便面对象。

Ioc与di的关系:
DI是依赖注入这个行为,而Ioc是控制反转容器,DI这个行为是用来实现完成Ioc的。

SpringIoc容器实现类

BeanFactory:
简介:
spring Bean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能规范,BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。它们之间的结构图如下:在这里插入图片描述
如图可见最终的默认实现类是 DefaultListableBeanFactory,他实现了所有的接口。那为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。

BeanFactory源码:

public interface BeanFactory {    
      
      //对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,    
      //如果需要得到工厂本身,需要转义           
      String FACTORY_BEAN_PREFIX = "&"; 
         
      //根据bean的名字,获取在IOC容器中得到bean实例    
      Object getBean(String name) throws BeansException;    
    
     //根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。    
      Object getBean(String name, Class requiredType) throws BeansException;    
     
     //提供对bean的检索,看看是否在IOC容器有这个名字的bean    
      boolean containsBean(String name);    
     
     //根据bean名字得到bean实例,并同时判断这个bean是不是单例    
     boolean isSingleton(String name) throws NoSuchBeanDefinitionException;    
     
     //得到bean实例的Class类型    
     Class getType(String name) throws NoSuchBeanDefinitionException; 

     //得到bean的别名,如果根据别名检索,那么其原名也会被检索出来    
    String[] getAliases(String name);         
 }

在BeanFactory里只对IOC容器的基本行为作了定义,根本不关心你的bean是如何定义怎样加载的。正如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心。
它的功能总结起来就是得到查找。
而要知道工厂是如何产生对象的,我们需要看具体的IOC容器实现,spring提供了许多IOC容器的实现。比如XmlBeanFactory,ClasspathXmlApplicationContext等。其中XmlBeanFactory就是针对最基本的ioc容器的实现,这个IOC容器可以读取XML文件定义的BeanDefinition(XML文件中对bean的描述),XmlBeanFactory就是基础的容器,ApplicationContext就是最强容器。ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能外,还为用户提供了以下的附加服务。从ApplicationContext接口的实现,我们看出其特点:

  1. 支持信息源,可以实现国际化。(实现MessageSource接口)
    2.访问资源。(实现ResourcePatternResolver接口,这个后面要讲)
  2. 支持应用事件。(实现ApplicationEventPublisher接口)

IoC容器的初始化?

IoC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本的过程。我们以ApplicationContext为例讲解,ApplicationContext系列容器也许是我们最熟悉的,因为web项目中使用的XmlWebApplicationContext就属于这个继承体系,还有ClasspathXmlApplicationContext等,其继承体系如下图所示:在这里插入图片描述

SpringIoc容器初始化的详细过程:

1)定位:
根据xml配置文件或者注解找到我们的bean资源(也就是我们在注解或者xml中写入的bean信息)。
2)载入:
将我们定位的resource载入到beandefinition中,此时并不会创建bean实例。
3)注册:
将载入了resource信息的beandefinition,的信息发布到springIOC容器中,注意此时任然没有创建bean实例。
实例的创建时间取决于lazy-init配置,默认为false,则以上三个过程完成后就会创建,如果配置为true,那么只有在使用getBean的时候才会完成Bean初始化,完成依赖注入。

Spring Bean的生命周期:

Java常规bean的生命周期:
常规的bean我们是通过new关键词来构建,会在java内存的堆中进行创建,并将这个对象的引用存入到相应的栈中,这就是一个对象的new关键字创建方法(略去类的加载过程)
,然后就是使用,线程结束,对象的引用被销毁。
Spring给bean带来了哪些改变:
1)过程上的变化,现在我们的bean的创建权是交给了容器,那么我们bean就相当于是直接放在了容器之中,我们在需要时直接将它的对象引用赋值给需要的地方即可,当然一个bean也不止用一次。
2)这样的方式就让一个bean那些事的参与者增加了,之前就是一个使用者一个bean本身,但现在有了容器、还有产生它的工厂。
*注:*正是这些变化会使我们的bean生命周期发生变化,例如我们需不需要知道bean的容器是谁?而原来并没有这个所谓的容器。而要通过bean看到它在那个容器之中自然需要一定的操作,具体的变化我们通过详细spring bean 的生命周期来看。
Spring bean生命周期详情:
生命周期全过程:
1)spring对bean进行实例化,默认bean是单例
2) spring对bean进行依赖注入
3) 如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法
4) 如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来
5) 如果bean实现了ApplicationContextAware()接口,spring将调用setApplicationContext()方法将应用上下文的引用传入
6) 如果bean实现了BeanPostProcessor接口,spring将调用它们的postProcessBeforeInitialization接口方法
7) 如果bean实现了InitializingBean接口,spring将调用它们的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会被调用
8) 如果bean实现了BeanPostProcessor接口,spring将调用它们的postProcessAfterInitialization接口方法
9) 此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁
10) 若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用
上面的过程调用的各种方法可分为3类:

Bean自身的方法配置文件中的init-method和destroy-method配置的方法、Bean对象自己调用的方法
Bean级生命周期接口方法BeanNameAware、BeanFactoryAware、InitializingBean、DiposableBean等接口中的方法
容器级生命周期接口方法InstantiationAwareBeanPostProcessor、BeanPostProcessor等后置处理器实现类中重写的方法

这就是spring bean生命周期的全过程,我们前面也说道了,这种周期的变化就是由于现在这种bean模式变化而引起的,这种情况我们并不陌生,在数据结构中,三方插件中,整个编程的学习中经常出现,对应这种变化模式我们作何理解呢?我们在对程序进行不断的功能增强。就需要我们为一些东西进行扩展修饰,就像spring IOC,我们为了降低程序的耦合性我们引入了IOC,有了容器这个概念,我们就相应的会增加一些功能。

依赖注入:

在整个生命周期中我们最常操作的对象就是依赖注入,依赖注入有三种方式:构造器注入、setter注入、接口注入
构造器注入
  构造器注入主要是依赖于构造方法去实现,构造方法可以是有参也可以是无参,我们在平常都是通过类的构造方法来创建类对象,以及给他赋值,同样Spring 也可以采用反射的方式,通过构造方法来完成注入注入(赋值),这就是构造器注入的原理,说了那么多我们就来看看代码的实现吧

/**
*
*  构造器注入  
*
*/
 
package com.xiaojiang.Spring;
 
public class Role {
     
    private int id;
    private String roleName;
    private String note;
     
    public Role(){}
     
    public Role(int id,String roleName, String note)
    {
       super();
        this.id = id;
        this.roleName = roleName;
        this.note = note;
    }     //setter,getter方法省略
 
}

applicationContext.xml文件

<!--构造器配置-->
 
<bean id="Role" class="com.xiaojiang.Spring.Role">
        <constructor-arg value="1" type="int"></constructor-arg>
        <constructor-arg value="yqd" type="java.lang.String"></constructor-arg>
        <constructor-arg value="qwer" type="java.lang.String"></constructor-arg>
    </bean>

constructor-arg元素用于定义类构造方法的参数,其中type用于定义参数的类型,也可以使用index来定义参数的位置,而这里的value是用于设置值,以上的代码就是通过一个Spring去装配一个Bean。
setter注入
  setter是Spring现在最主流的注入方式,它可以利用Java Bean 规范所定义set/get方法来完成注入,可读性灵活性高,它不需要使用构造器注入时出现的多个参数,它可以把构造方法声明成无参构造,再使用setter注入设置相对应的值,其实也是通过java反射技术去实现的.
xml代码:

<!--配置setter注入-->
<bean id="Role" class="com.xiaojiang.Spring.Role">
        <property name="id" value="1"><property>
        <property name="roleName" value="yqd"><property>
        <property name="note" value="qwer"><property>
</bean>   

接口注入

注:

结构图为网络资源

最后一句话:

看到此处便是缘,请您再听我一言;
新生博主甚是难,还请原谅把你烦;
博文写了没人看,博主这活没法干;
看了不评就走人,他人怎知行不行;
看了评论又推荐,博主心里笑开颜。
ps:就想皮一下,但还是希望你能指出错误,如果觉得可以夸奖一下就更好了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值