spring 源码学习---spring基础之(IOC和DI)

   spring是一个轻量级的开源的框架。 

    Spring 是个 java 企业级应用的开源开发框架。Spring 主要用来开发 Java 应用,但是有些扩展是针对构建 J2EE 平台的 web 应用。Spring 框架目标是简化 Java 企业级应用开发,并通过 POJO 为基础的编程模型促进 良好的编程习惯。 

   对此,她主要采取了 4 个关键策略:

  •       1,基于 POJO 的轻量级和最小侵入性编程;
  •       2,通过依赖注入和面向接口松耦合;
  •       3,基于切面和惯性进行声明式编程;
  •       4,通过切面和模板减少样板式代码; 而他主要是通过:面向 Bean、依赖注入以及面向切面这三种方式来达成的。
     

   其核心两部分是:1、ioc(控制反转) 2 、aop 面向切面编程

  优缺点:

         

一、依赖注入的基本概念

  Spring 设计的核心 org.springframework.beans 包(架构核心是 org.springframework.core 包),它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用,而是由服务器将 其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现, 允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。 

BeanFactory 支持两个对象模型

   1,单例Singleton :模型提供了具有特定名称的对象的共享实例,可以在查询时对其进行检索。Singleton 是 默认的也是最常用的对象模型。对于无状态服务对象很理想。

   2,原型 Prototype:模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时,原型模型最适 合。 Bean 工厂的概念是 Spring 作为 IOC 容器的基础。IOC 则将处理事情的责任从应用程序代码转移到 框架。

二、AOP 编程理念

  面向切面编程,即 AOP,是一种编程思想,它允许程序员对横切关注点或横切典型的职责分界线的 行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面(切面),它将那些影响多个类的行 为封装到可重用的模块中。 

    AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型 的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势 就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用 Spring AOP 编写的应 用程序代码是松散耦合的。

三 、spring 体系

    组成 Spring 框架的每个模块集合或者模块都可以单独存在,也可以一个或多个模块联合实现。每个模 块的组成和功能如下

    1.核心容器:由 spring-beans、 spring-core、 spring-context 和 spring-expression(Spring Expression Language, SpEL) 4 个模块组成。 

    spring-beans 和 spring-core 模块是 Spring 框架的核心模块,包含了控制反转(Inversionof Control, IOC)和依赖注入(Dependency Injection, DI)BeanFactory 接口是 Spring 框架中 的核心接口,它是工厂模式的具体实现。BeanFactory 使用控制反转对应用程序的配置和依赖性规范与 实际的应用程序代码进行了分离。但 BeanFactory 容器实例化后并不会自动实例化 Bean,只有当 Bean 被使用时 BeanFactory 容器才会对该 Bean 进行实例化与依赖关系的装配。 

    spring-context 模块构架于核心模块之上,他扩展了 BeanFactory,为她添加了 Bean 生命周期 控制、框架事件体系以及资源加载透明化等功能。此外该模块还提供了许多企业级支持,如邮件访问、 远程访问、任务调度等,ApplicationContext 是该模块的核心接口,她是 BeanFactory 的超类,与 BeanFactory 不同,ApplicationContext 容器实例化后会自动对所有的单实例 Bean 进行实例化与 依赖关系的装配,使之处于待用状态。 

    spring-expression 模块是统一表达式语言(EL)的扩展模块,可以查询、管理运行中的对象, 同时也方便的可以调用对象方法、操作数组、集合等。它的语法类似于传统 EL,但提供了额外的功能, 最出色的要数函数调用和简单字符串的模板函数。这种语言的特性是基于 Spring 产品的需求而设计, 他可以非常方便地同 Spring IOC 进行交互。 

  2.AOP 和设备支持:由 spring-aop、spring-aspects 和 spring-instrument 3 个模块组成。 

   spring-aop 是 Spring 的另一个核心模块,是 AOP 主要的实现模块。作为继 OOP 后,对程序员影 响最大的编程思想之一,AOP 极大地开拓了人们对于编程的思路。在 Spring 中,他是以 JVM 的动态代 理技术为基础,然后设计出了一系列的 AOP 横切实现,比如前置通知、返回通知、异常通知等,同时, Pointcut 接口来匹配切入点,可以使用现有的切入点来设计横切面,也可以扩展相关方法根据需求进 行切入。 

  spring-aspects 模块集成自 AspectJ 框架,主要是为 Spring AOP 提供多种 AOP 实现方法。

  3.数据访问及集成:由 spring-jdbc、spring-tx、spring-orm、spring-jms 和 spring-oxm 5 个 模块组成

    spring-jdbc 模块是 Spring 提供的 JDBC 抽象框架的主要实现模块,用于简化 Spring JDBC。主 要是提供 JDBC 模板方式、关系数据库对象化方式、SimpleJdbc 方式、事务管理来简化 JDBC 编程,主 要实现类是 JdbcTemplate、SimpleJdbcTemplate 以及 NamedParameterJdbcTemplate。

   spring-tx 模块是 SpringJDBC 事务控制实现模块。使用 Spring 框架,它对事务做了很好的封装, 通过它的 AOP 配置,可以灵活的配置在任何一层;但是在很多的需求和应用,直接使用 JDBC 事务控制 还是有其优势的。其实,事务是以业务逻辑为基础的;一个完整的业务应该对应业务层里的一个方法; 如果业务操作失败,则整个事务回滚;所以,事务控制是绝对应该放在业务层的;但是,持久层的设计 则应该遵循一个很重要的原则:保证操作的原子性,即持久层里的每个方法都应该是不可以分割的。所 以,在使用 Spring JDBC 事务控制时,应该注意其特殊性。 

  spring-orm 模块是 ORM 框架支持模块,主要集成 Hibernate, Java Persistence API (JPA) 和 Java Data Objects (JDO) 用于资源管理、数据访问对象(DAO)的实现和事务策略。 

   spring-jms 模块(Java Messaging Service)能够发送和接受信息,自 Spring Framework 4.1 以后,他还提供了对 spring-messaging 模块的支撑。 

  4.Web:由 spring-web、spring-webmvc、spring-websocket 和 spring-webflux 4 个模块组成。 

    spring-web 模块为 Spring 提供了最基础 Web 支持,主要建立于核心容器之上,通过 Servlet 或 者 Listeners 来初始化 IOC 容器,也包含一些与 Web 相关的支持。 

    spring-webmvc 模 块 众 所 周 知 是 一 个 的 Web-Servlet 模 块 , 实 现 了 Spring MVC (model-view-Controller)的 Web 应用。 

     spring-webflux 是一个新的非堵塞函数式 Reactive Web 框架,可以用来建立异步的,非阻塞, 事件驱动的服务,并且扩展性非常好。 

四、  IOC控制反转

IOC是一种容器,DI是其一种实现,包括:依赖查找和依赖注入

IOC编程思路实现有2种:

1.依赖查找

    就是应用程序里面还是要调用容器的bean查找接口查找bean实例
     缺点:还是有侵入性,性能低。

2.依赖注入

  直接在容器启动时通过构造器,getter setter等形式注入依赖。
  优点:性能高,侵入小

1、浅谈控制反转(Inversion of Control,IOC)

      我们首先先来了解一下控制二字,也就是在控制“正”转的情况下,在任何一个有请求作用的系统当中,至少需要有两个类互相配合工作,在一个入口类下使用new关键字创建另一个类的对象实例。

      这就好比在面向对象编程的思想下,“我“充当一个入口类,在这个入口类中,我每次吃饭的时候都要买一双一次性筷子(每一次使用都要new一次),在这样的关系下,是”我“(即调用者)每次都要”主动“去买一次性筷子(另一个类)。我对筷子说你老老实实的过来我的手上,是我控制了筷子,那好,在这种控制正转的关系下,放在现实生活当中,肯定是不现实的,而且人是懒惰的,他总会去创造出更加方便自己生活的想法。

      更确切的做法是,买一双普通的筷子(非一次性),把他放在一个容器当中(在Spring中叫做IOC容器),你需要使用的时候就对容器说:IOC我想要用筷子(向容器发出请求),接着筷子就会”注入“到的手上,而在这个过程当中,你不再是控制方,反而演变成一名请求者(虽然本身还是调用者),依赖于容器给予你资源,控制权坐落到了容器身上,于是这就是人们俗称的控制反转。

2、初涉依赖注入(Dependency Injection)  

       同样接着上面的例子,在控制反转的统一下,筷子是怎么来到我的手上(即我们是如何获得请求的类),这就是一个依赖注入的过程。

     依赖注入,是 IOC 的一个方面,是个通常的概念,它有 多种解释。这概念是说你不用创建对象,而只需要描述 它如何被创建。你不在代码里直接组装你的组件和服 务,但是要在配置文件里描述哪些组件需要哪些服务, 之后一个容器(IOC 容器)负责把他们组装起来。 

3、再谈IOC与DI

      设计原则中好莱坞原则描述到,“别找我们,我们找你”,百度百科上对这点描述是“不要给我们打电话,我们会给你打电话(don‘t call us, we‘ll call you)”这是著名的好莱坞原则。

       在好莱坞,把简历递交给演艺公司后就只有回家等待。由演艺公司对整个娱乐项的完全控制,演员只能被动式的接受公司的差使,在需要的环节中,完成自己的演出。

     这一点完美的提现了在IOC身上,IOC所注重的是设计思想上,从一个常规的创建对象的做法,即new一个对象,转变成向IOC容器递交”简历“,被动的等待IOC容器返回资源给你。控制反转即指的是”演艺公司控制演员“,而说到依赖,则是“演员需要公司混饭”,我们所需求的对象,需要依赖容器来获得,这个过程即是依赖注入。本质上IOC和DI是同一思想下不同维度的表现。

4、依赖注入的方式

     1、构造器依赖注入:构造器依赖注入通过容器触发一个类 的构造器来实现的,该类有一系列参数,每个参数代表 一个对其他类的依赖。 

    2、Setter 方法注入:Setter 方法注入是容器通过调用无参 构造器或无参 static 工厂 方法实例化 bean 之后,调用 该 bean 的 setter 方法,即实现了基于 setter 的依赖注 入。 

     问题: 哪种依赖注入方式你建议使用,构造器注入,还是 Setter 方法注入?

       你两种依赖方式都可以使用,构造器注入和 Setter 方法 注入。

        最好的解决方案是用构造器参数实现强制依赖setter 方法实现可选依赖。 

 

4、IOC的底层原理

 1)xml配置文件

2)dom4j解析配置文件

3)工厂设计模型

4)反射

例如:第一步创建类

public class UserService{}

第二步 配置xml配置文件,配置要创建的对象类

<bean id="userService" class="com.springTest.service.UserService"></bean>

第三步创建工厂类,使用dom4j解析配置文件+反射

public class UserFactory{

    public static UserService getService(){

        1使用dom4j解析xml文件根据ID值userService,得到ID值对应的class书写值

      String classValue="class属性值"

  //使用反射创建类对象

      Class clazz= Class.forName(classValue);

UserService userService = clazz.newInstance();

return userService;

 }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值