Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

Easter79
• 阅读 706

什么是IoC

        IoC容器,最主要的就是完成对象的创建以及维护对象的依赖关系等。

       所谓控制反转,包括两部分:一是控制,二是反转,就是把传统方式需要由代码来实现对象的创建、维护对象的依赖关系,反转给容器来帮忙管理和实现。所以我们必须要创建一个容器,同时需要一种描述来让容器创建对象与对象的关系。

       IoC容器是怎么完成初始化的以及对象创建的。Spring只需要四步:

          Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

1、定位

      我们知道对象和对象关系可以用xml,properties文件等语义化配置文件表示,我们要怎样定位这些文件呢?Spring为我们设置了资源加载器和资源定位的方法,可能是classpath(类路径),filesystem(文件系统),或者URL网络资源,或者web容器(servletContext)等。

2、载入

      我们定位到资源文件之后 ,需要将这些资源文件载入,在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证使用的是新建立起来的IoC容器。

3、解析

      有了配置文件,还需要对配置文件进行解析。不同的配置文件对对象的描述不一样,自定义声明式的,都必须转化成统一的描述定义。

4、注册

      向IoC容器注册解析后的BeanDefinition,此时我们IoC容器初始化完成。

       到这,相信你对IoC容器一定又有了更进一步的认识。下面我们再通过原来的一个例子,解释一下IoC的核心。

IoC的核心-BeanFactory

项目的包图:

Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

Spring的配置文件:

[html] view plain copy

  1.   

  2. <beans xmlns="http://www.springframework.org/schema/beans"  

  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

  4.          xmlns:aop="http://www.springframework.org/schema/aop"  

  5.          xmlns:tx="http://www.springframework.org/schema/tx"  

  6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd  

  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd  

  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">  

  9.       

  10.       

  11.       

  12.       

  13.           

  14.           

  15.           

  16.           

  17.       

  

业务逻辑层:
UserManager接口:添加用户的方法

[java] view plain copy

  1. public interface UserManager {  

  2.     public void addUser(String userName,String password);  

  3. }

  

UserManager实现

[java] view plain copy

  1. import com.tgb.spring.dao.UserDao;  

  2. public class UserManagerImpl implements UserManager{  

  3.     private UserDao userDao;  

  4.     //使用设值方式赋值  

  5.     public void setUserDao(UserDao userDao) {  

  6.         this.userDao = userDao;  

  7.     }  

  8.     @Override  

  9.     public void addUser(String userName, String password) {  

  10.         userDao.addUser(userName, password);  

  11.     }  

  12. }

  

数据访问层:

UserDao接口:添加用户的方式

[java] view plain copy

  1. public interface UserDao {  

  2.     public void addUser(String userName,String password);  

  3. }

  

UserDao两种实现(Mysql和Oracle)

[java] view plain copy

  1. public class UserDao4MysqlImpl implements UserDao{  

  2.     @Override  

  3.     public void addUser(String userName, String password) {  

  4.         //打印访问MySQL的相关信息  

  5.         System.out.println("UserDao4MysqlImpl.addUser");  

  6.     }  

  7. }

  

[java] view plain copy

  1. public class UserDao4OracleImpl implements UserDao{  

  2.     @Override  

  3.     public void addUser(String userName, String password) {  

  4.         //打印访问Oracle的相关信息  

  5.         System.out.println("UserDao4OracleImpl.addUser");  

  6.     }  

  7. }

  

客户端:

[java] view plain copy

  1. import org.springframework.beans.factory.BeanFactory;  

  2. import org.springframework.context.support.ClassPathXmlApplicationContext;  

  3. import com.tgb.spring.manager.UserManager;  

  4. public class Client {  

  5.     public static void main(String[] args){  

  6.         BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");  

  7.         //到IOC容器中获取UserManager  

  8.         UserManager userManager = (UserManager) factory.getBean("userManager");  

  9.         //UserManager使用UserDao,在配置文件已经有依赖关系  

  10.         userManager.addUser("jiuqiyuliang", "123456");        

  11.     }  

  12. }

  

运行效果图:

Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

         在我们客户端的代码中,初始化IoC容器时,我们使用的是Spring最最核心的接口——BeanFactory, 它可以说是 spring 的心脏。 Spring 的 ioc 就是围绕着BeanFactory 展开的。我们通过类图看一下Spring为我们提供哪些最基本的服务:  

Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

        从上图中我们可以看到BeanFactory是最顶层的接口,它定义了IOC容器的基本功能。其中BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能规范,BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。但是从上图中我们可以发现最终的默认实现类是 DefaultListableBeanFactory,他实现了所有的接口。那为何要定义这么多层次的接口呢?查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为、最基本的IOC容器接口BeanFactory

      我们通过源码看一下BeanFactory为我们提供的最基本服务:

[java] view plain copy

  1. public interface BeanFactory {  

  2.     /** 

  3.      * Used to dereference a {@link FactoryBean} instance and distinguish it from 

  4.      * beans created by the FactoryBean. 

  5.      * 对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,     

  6.      * 如果需要得到工厂本身,需要转义  

  7.      */  

  8.     String FACTORY_BEAN_PREFIX = "&";  

  9.     /** 

  10.      * Return an instance, which may be shared or independent, of the specified bean. 

  11.      * 根据bean的名字,获取在IOC容器中得到bean实例 

  12.      */  

  13.     Object getBean(String name) throws BeansException;  

  14.     /** 

  15.      * Return an instance, which may be shared or independent, of the specified bean. 

  16.      * 根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。 

  17.      */  

  18.      T getBean(String name, Class requiredType) throws BeansException;  

  19.     /** 

  20.      * Return the bean instance that uniquely matches the given object type, if any. 

  21.      * 根据Class类型来得到bean实例,增加了类型安全验证机制。 

  22.      */  

  23.      T getBean(Class requiredType) throws BeansException;  

  24.     /** 

  25.      * Return an instance, which may be shared or independent, of the specified bean. 

  26.      * 

  27.      */  

  28.     Object getBean(String name, Object... args) throws BeansException;  

  29.     /** 

  30.      * Return an instance, which may be shared or independent, of the specified bean. 

  31.      */  

  32.      T getBean(Class requiredType, Object... args) throws BeansException;  

  33.     /** 

  34.      * Does this bean factory contain a bean definition or externally registered singleton 

  35.      * instance with the given name? 

  36.      * 提供对bean的检索,看看是否在IOC容器有这个名字的bean   

  37.      */  

  38.     boolean containsBean(String name);  

  39.     /** 

  40.      * Is this bean a shared singleton? That is, will {@link #getBean} always 

  41.      * return the same instance? 

  42.      * 根据bean名字得到bean实例,并同时判断这个bean是不是单例  

  43.      */  

  44.     boolean isSingleton(String name) throws NoSuchBeanDefinitionException;  

  45.     /** 

  46.      * Is this bean a prototype? That is, will {@link #getBean} always return 

  47.      * independent instances? 

  48.      */  

  49.     boolean isPrototype(String name) throws NoSuchBeanDefinitionException;  

  50.     /** 

  51.      * Check whether the bean with the given name matches the specified type. 

  52.      * More specifically, check whether a {@link #getBean} call for the given name 

  53.      * would return an object that is assignable to the specified target type. 

  54.      *  

  55.      */  

  56.     boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;  

  57.     /** 

  58.      * Determine the type of the bean with the given name. More specifically, 

  59.      * determine the type of object that {@link #getBean} would return for the given name. 

  60.      * 得到bean实例的Class类型 

  61.      */  

  62.     Class<?> getType(String name) throws NoSuchBeanDefinitionException;  

  63.     /** 

  64.      * Return the aliases for the given bean name, if any. 

  65.      * All of those aliases point to the same bean when used in a {@link #getBean} call. 

  66.      * 得到bean的别名,如果根据别名检索,那么其原名也会被检索出来 

  67.      */  

  68.     String[] getAliases(String name);

  

总结

         BeanFactory只对IoC容器的基本行为作了定义或者是规范,根本没有具体实现。

         下篇博文我会为大家详细的介绍“屌丝版”BeanFactory和高帅富版BeanFactory。敬请关注。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
SpringIOC官方文档解读
IoC容器本章介绍了Spring的控制反转(IoC)容器。1.1。SpringIoC容器和Bean简介本章介绍了反转控制(IoC)原则的Spring框架实现。IoC也称为依赖注入(DI)。在此过程中,对象可以通过①构造函数参数(),②工厂方法的参数③或在构造或从工厂方法返回后在对象实例上设置的属性来定义其依
Stella981 Stella981
3年前
Spring Ioc之BeanFactory
   IoC(InversionofControl),即所谓的控制反转,就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器(BeanFactory)负责的。   Spring通过配置文件(或者注解、JavaConfig)描述Bean和Bean之间的依赖关系,利用反射机制实例化Bean并建立Bean之间的依赖关系。Spr
Easter79 Easter79
3年前
Spring系列(五) 容器初始化过程源码
IoC/DI的概念容器是Spring的核心之一(另一个核心是AOP).有了容器,IOC才可能实现.什么使IoC?IoC就是将类自身管理的与其由依赖关系的对象的创建/关联和管理交予容器实现,容器按照配置(比如xml文件)来组织应用对象的创建和关联.什么使DI?DI是IoC的实现方式,由容器
Wesley13 Wesley13
3年前
JAVA日常记录
11.IOC的优点是什么IOC(InversionofControl)控制反转,将控制权(创建对象和对象之间的依赖关系的权利)交给spring容器。接口驱动设计(InterfaceDrivenDesign)的好处,可以灵活提供不同的子类实现(其实就是解耦),提高程序的灵活性、可扩展性和可维护性。IOC模式将耦合代
Stella981 Stella981
3年前
Spring 学习笔记(二):SpringIoC
1IoC与DIIoC是InversionofControl的简称,也就是控制反转。通常来说,创建对象需要调用者手动创建,也就是newXXX()的方式。当Spring框架出现后,对象的实例不再由调用者创建,而是由Spring容器创建,这样控制权就由调用者转移到Spring容器,控制权发生了反
Easter79 Easter79
3年前
Spring源码阅读——3
SpringIoC容器1、IoC容器概述控制反转、IoC容器、依赖注入控制反转:不是什么技术,而是一种设计思想。Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。IoC容器:IoC容器控制了对象的
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k