《Spring in Action》是一本很不错的Spring工具书,作者Craig Walls是Spring核心开发人员,特别喜欢用有趣的例子减少读者对枯燥理论和恐怖名词的畏惧感。受到他的影响,我在学习和做笔记的过程中,也试图不那么严肃,把自己喜欢的一些东西引入到编程实践中。

上一篇文章《用一个极简的Spring Demo开始记录2018年的满血转身》用一个很简单的Demo作为学习Spring的开始,今天开始用更多的编程实践来记录Spring更深入的知识。

Spring Framework为简化Java开发而生,它的每个机制都仅仅围绕着四个核心策略

  1. 基于POJO(Plain Ordinary Java Object)的轻量级和最小侵入性编程
  2. 通过依赖注入(DI)和面向接口实现松耦合
  3. 基于切面(AOP)进行声明式编程
  4. 通过切面减少样板式代码

Spring是轻量级的框架,而早期版本的Struts、WebWork等重量级框架存在的问题:强迫开发者按照框架接口要求编写大量冗余代码,导致应用被框架绑架,通常也难以编写测试代码

每当提起Spring,两个名词一定会脱口而出:依赖注入(DI)和面向切面编程(AOP),接下来分别说一说他们俩。

依赖注入

  • 如何理解耦合?耦合具有两面性:一方面,紧密耦合的代码难以测试、复用和理解;另一方面,一定程度的耦合是必须的,没有耦合的代码什么也做不了。因此,耦合是必须的,但应当小心谨慎的使用
  • 通过依赖注入的方式,为耦合提供了一种良好的解决手段。通过依赖注入,对象的依赖关系由负责协调系统中各个对象关系的第三方组件在创建对象时设定。对象本身无需自行创建和管理和其他对象的依赖关系。依赖注入是一个更抽象的名词--控制反转的(IoC)的一种实现方式
  • 通过依赖注入的方式,实现了对象间的松耦合。依赖注入推崇通过接口,而非具体实现或初始化的过程,来表明依赖关系。这种依赖能够在对象本身毫不知情的情况下,用不同的具体实现进行替换(正是利用了Java面向对象编程的动态绑定概念)
  • 创建对象之间的协作关系通常称为“装配”。Spring有多种装配方式,常见的是通过XML或者注解的方式

《Spring in Action》在介绍依赖注入时,用了骑士作为例子。骑士的例子很棒,但由于好多单词都不认识,我还是引用挚爱的美剧 《权力的游戏》中的人物作为依赖注入的编程实践

出场人物:“弑君者”詹姆·兰尼斯特,正义勇敢的艾德·斯塔克,“疯王”伊利斯·塔格里安(他其实只出现在打印中)

说明:应该尽可能习惯于面向接口的编程。面向接口是Spring推崇的,能够充分利用Java的动态绑定机制,悄无声息的改变运行态的对象类型,最大限度减少代码变更。

Knight接口,代表被各种各样的骑士,但这些骑士都要实现actionOnExplore()方法,代表其探险之旅干了什么

package com.study.spring.knights;public interface Knight {public void actionOnExplore();
}

Explore接口,只有action()一个方法,代表探险具体的动作

package com.study.spring.knights;public interface Explore {public void action();
}

HandsomeKnight,实现Kinght接口,代表帅哥类型的骑士

package com.study.spring.knights;public class HandsomeKnight implements Knight {private Explore explore;public HandsomeKnight(Explore explore) {this.explore = explore;}@Overridepublic void actionOnExplore() {explore.action();}
}

BraveKnight,实现Kinght接口,代表勇敢类型的骑士

package com.study.spring.knights;public class BraveKnight implements Knight {private Explore explore;public BraveKnight(Explore explore) {this.explore = explore;}@Overridepublic void actionOnExplore() {explore.action();}}

KingslayerExplore,实现Explore接口,想必《权游》爱好者已经明白它要干什么了吧

package com.study.spring.knights;public class KingslayerExplore implements Explore {@Overridepublic void action() {System.out.println("Hi, I'm Jamie Lannister. Goodbye Aerys II Targaryen ...");}
}

OverthrowExplore,实现Explore接口,Overthrow啥意思?友情做个广告:有道词典,牛逼到不行不行的

package com.study.spring.knights;public class OverthrowExplore implements Explore {@Overridepublic void action() {System.out.println("Hi, I'm Eddard Stark. I overthrow Aerys II Targaryen with my brother Robert Baratheon...");}
}

然后就是在XML中定义Bean的依赖注入关系。

我将KingslayerExplore和OverthrowExplore以构造参数的方式分别注入到HandsomeKnight和BraveKnight中。当Spring Framework被调度起来后,会在其ApplicationContext容器中,创建上述四个实例,并根据注入关系建立起依赖关系。在HandsomeKnight和BraveKnight中,完全看不到new出一个Explore对象的语句。在运行过程中,不知不觉就被注入了具体的Explore。

如果我们觉得HandsomeKnight不应该被冠以Kingslayer之名,完全可以注入一个LoveSisterExplore,哈哈哈...

<?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    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  <!-- Inject through constructor --><bean id="jamieLannister" class="com.study.spring.knights.HandsomeKnight"><constructor-arg ref="kingslayer"/></bean> <bean id="eddardStark" class="com.study.spring.knights.BraveKnight"><constructor-arg ref="overthrow"/></bean><bean id="kingslayer" class="com.study.spring.knights.KingslayerExplore"/><bean id="overthrow" class="com.study.spring.knights.OverthrowExplore"/>  </beans>  

最后,写一个KnightMain,调度起Spring Framework,加在KnightXML

在main方法中,使用Spring框架接口,分别得到不同类型的Knight

package com.study.spring.knights;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class KnightMain {public static void main(String[] args) {//Create IoC container through XMLApplicationContext apc = new ClassPathXmlApplicationContext("Knight.xml");  //A Knight Jamie Lannister instance injected Knight knight = (Knight)apc.getBean("jamieLannister");  //Invoke Jamie methodknight.actionOnExplore();//A Knight Eddard Stark instance injected knight = (Knight)apc.getBean("eddardStark");  //Invoke Eddard methodknight.actionOnExplore();}}

运行结果如期所至:

3月 08, 2018 10:20:43 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7fac631b: startup date [Thu Mar 08 22:20:43 CST 2018]; root of context hierarchy
3月 08, 2018 10:20:43 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [Knight.xml]
Hi, I'm Jamie Lannister. Goodbye Aerys II Targaryen ...
Hi, I'm Eddard Stark. I overthrow Aerys II Targaryen with my brother Robert Baratheon...

面向切面编程

  • 依赖注入让相互协作的软件组件保持松耦合,AOP则用来将遍布应用各处的功能分离出来形成可复用的组件。诸如日志、事件、事务管理、安全等系统服务经常要显示的融入到业务逻辑之中。这些系统服务通常称为横切关注点,因为它们总是跨越系统的多个组件
  • 关注点分散在多个组件中,对代码带来的明显损害是:1)关注点代码重复出现在系统的多个软件组件中,修改起来异常耗时;2)系统因这些和业务逻辑不强相关的代码变得异常混乱
  • 比如下图的示例,业务对象不仅知道要记录日志、进行安全控制和参与事务,还要亲自调用这些服务或接口,但它们并不是核心业务

  • 利用AOP,可以用这些功能层来包裹核心业务层。功能层以声明的方式应用到系统中,核心业务都可以不知道这些功能层的存在,是一种业务逻辑和非业务逻辑分离的编程模式

未完待续……

Spring Framework基础知识:依赖注入与面向切面相关推荐

  1. Spring IoC和DI XML方式 注解方式 依赖注入 AOP面向切面

    初识Spring框架 时代变迁 原始时代我们用一个jsp搞定一切,但如此开发大型项目时我们遇到了问题,前端美化的代码和后端的代码交织,代码中又有html.js.css样式,又有业务逻辑和数据库访问代码 ...

  2. 我的控制反转,依赖注入和面向切面编程的理解

    感谢http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/ 的供图 1.什么是控制? 如下图所示,我们看到了 软件系统中 对象的 高耦合现象.全体齿轮的转 ...

  3. Spring框架基础知识

    本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , ...

  4. Spring 的控制反转/依赖注入

    第一章 Spring 的控制反转/依赖注入 回顾 增删改查. 课前测: 本章内容 spring:春天 IOC:将创建对象的权力交给 spring 核心容器去控制.工厂模式 BeanFactory: 懒 ...

  5. 2021 版 Spring Boot 基础知识复习手册(2w字,建议收藏)

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客: ...

  6. Spring Bean 装配和依赖注入

    Spring IOC 容器的依赖注入工作可以分为两个阶段.第一个阶段可以认为是构建和收集 Bean 定义的阶段,在这个阶段中,我们可以通过 xml 或者 Java 代码的方式定义一些 Bean,然后通 ...

  7. Spring的核心机制依赖注入简介

    Spring能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的管理下有机地协调.运行.Spring将各层的 ...

  8. 关于mysql注入说法正确的是_1. 在 Spring中,下列关于 依赖注入 的 说法 , 正确的是( ) 。_学小易找答案...

    [简答题]1基本流程练习 2时间轴嵌套 3简单应用 [简答题]请解释什么是MVC? [多选题]在 Hibernate 中,下 列 说法正确的有 [多选题]1. 关于 Spring,下列说法不正确的是( ...

  9. AngularJs 基础教程 —— 依赖注入

    为什么80%的码农都做不了架构师?>>>    本文为 H5EDU 机构官方 HTML5培训 教程,主要介绍:AngularJs 基础教程 -- 依赖注入 AngularJS 依赖注 ...

最新文章

  1. 为什么《30天自制操作系统》封面中的猫是两只尾巴
  2. golang中的strings.Repeat
  3. 8.6 多元高斯分布模型-机器学习笔记-斯坦福吴恩达教授
  4. shell 替换字符串的几种方法,变量替换${},sed,awk
  5. window下nginx反向代理配置
  6. Win10开启Linux调试adb(从此告别虚拟机)
  7. table中加表单元素怎么验证_el-table嵌入表单元素注意事项(验证规则prop写法与数据初始化)...
  8. 中燃料场报表生成器--出库报表
  9. java8配置环境变量_java8环境变量设置
  10. python应对反爬虫策略_python解决网站的反爬虫策略总结
  11. 数字后端基本概念介绍Wire
  12. 张云茹计算机,重庆理工大学药学与生物工程学院研究生导师简介-张云茹
  13. Q2增收不增利,“怪兽”无法给自己“充电”
  14. 查询加日期oracle,Oracle查询优化日期运算实例详解
  15. js-xlsx 读取Excel解析
  16. 多可文档管理的数据备份
  17. 这是一页纸商业计划书 (Business Plan) 模板(转)
  18. Android Clock控件
  19. vue 引用网络css_Vue 引入外部CSS文件
  20. 同态加密:分圆多项式简介

热门文章

  1. IDEA中的全局批量替换正则表达式
  2. js中字符串分割成数组split()方法
  3. 2021年安全员-A证(山东省)考试题库及安全员-A证(山东省)试题及解析
  4. 【云计算】企业云计算成熟度 发展四部曲
  5. 【Vue】Class与Style的绑定 —— 绑定对象与数组
  6. UE4数字孪生材质(四)
  7. Java基础:int与Integer区别
  8. php 数组字符串输出,php遍历数组输出成字符串例子
  9. 医院体检管理系统说明书
  10. 诡异的精度diff追查