重新来认识你的老朋友SPRING框架

欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系。本系列教程希望您能站在上帝的角度去观察(了解)Java体系。使Java的各种后端技术在你心中模块化;让你在工作中能将Java各个技术了然于心;能够即插即用。本章我们来一起了解你的老朋友Spring框架。 Spring这个词对于开发者想必不会陌生,可能你每天都在使用Spring,享受着Spring生态提供的服务,理所当然的用着SpringIOC和SpringAOP去实现老板交给你的功能 ,唔 它就是这样使用的(类声明为Bean组件,然后注入),没错 能完成老板任务,没毛病。如果向你提问什么是Spring,Spring有什么核心功能呢,你会想:这太简单了,Spring就是框架嘛,Spring核心功能就是IOC和AOP,So Easy!!可是你真的了解Spring吗?带着这个疑问让我们一起来重新了解一下Spring!本文所有示例源码下载 Spring的起源和根本使命 Spring是一个开源框架,最早由Rod Johnson创建,是为了解决企业级应用开发的复杂性而创建的。很多框架都宣称在某些方面针对Java开发做出了简化,但是Spring的目标是致力于全方位简化Java开发,这也是Spring的根本使命 "简化Java开发" Spring如何简化Java开发 为了降低Java开发的复杂性,Spring采取了以下4种关键策略,请务必牢记下面4中策略于心,这样会帮助你更深的理解Spring。下面我们来逐一解读每一条策略,你就能明白Spring是如何简化Java开发的。 基于POJO的轻量级和最小侵入性编程 通过依赖注入和面向接口实现松耦合 基于切面和惯例进行声明式编程 通过切面和模板减少样版式代码 1. 基于POJO的轻量级和最小侵入性编程 Spring竭力避免因自身的API而弄乱你的代码。Spring不会强迫你实现Spring规范的接口或继承Spring规范的类。相反,在一个基于Spring构建的应用中,应用中的类没有任何痕迹表明你使用了Spring。最坏的情况就是你在应用的类中发现了Spring的相关注解,但它依然是POJO,下面我们来看一个在Spring中的一个POJO例子。example1实例源码下载 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 20:32 2018-09-26 * @Modified By: */ public class HelloSpringBean { public String sayHello() { return "Hello Spring!!!"; } } 复制代码 你可以看到,这就是一个POJO(简单的JAVA类),没有任何地方表明它是Spring组件,Spring非侵入式编程模型意味着这个类在Spring应用和非Spring应用中都可以发挥同样的作用。尽管看起来很简单;但Spring通过IOC(Inversion of Control)管理这个POJO,然后通过DI(Dependency Inject)来注入他们,这个POJO就变的魔力十足;那么DI是如何帮助应用对象彼此之间保持松耦合的呢? 2. 通过依赖注入和面向接口实现松耦合 来我们一起来看一下一个简单的POJO example2实例源码下载 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 07:44 2018-09-27 * @Modified By: */ public class BeautifulGirl implements Gril { private EatAction eat; public BeautifulGirl() { this.eat = new EatAction(); } @Override public void action() { eat.action(); } } 复制代码 在BeautifulGirl(可爱的小女孩)这个类中,在构造方法中创建一个EatAction(吃饭动作)。这样就极大限制了BeautifulGirl(可爱的小女孩)的能力;如果现在小女孩需要去玩耍呢?或者需要去睡觉呢?真是太抱歉了,BeautifulGirl(可爱的小女孩)只会吃东西这个动作。这是什么原因呢?这就是BeautifulGirl(可爱的小女孩)和EatAction(吃饭动作)这两个类紧紧耦合在了一起!紧密耦合同时会造成代码的难以测试,难以服用,难以理解,并且典型地表现出"打地鼠“式的Bug特性(修复一个Bug,将会出现一个或多个新Bug),所以我们可以知道耦合是必须的,但必须谨慎管理耦合,但是怎么才算是谨慎处理耦合关系呢? 上图所示,DI(依赖注入)会将所依赖关系自动交给目标对象,而不是让对象本身创建所依赖对象。对象的依赖关系将由系统中负责协调个对象依赖关系的第三方组件(类似Spring)在创建对象的时候设定。现在我们明白了通过DI依赖注入可以将对象之间依赖关系轻松解耦,那么我们来看一下简单的实例吧。 example3实例源码下载 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 07:44 2018-09-27 * @Modified By: */ public class BeautifulGirl implements Gril { private Action action; public BeautifulGirl(Action action) { this.action = action; } @Override public void action() { action.action(); } } 复制代码 从上面实例代码中可以看到BeautifulGirl本身并没有创建任何的动作,而是通过构造方法传入一个实现了Action(动作)接口的实现类即可,也就是说BeautifulGirl可以完成任意实现了Action接口的动作(睡觉啦...玩耍啦...旅行啦....)。这里的要点是BeautifulGirl没有与任何特定的Action发生耦合。BeautifulGirl只需要的是一个实现Action接口就行,对象本身只是通过接口(而非具体实现或初始化过程)来表明依赖关系,那么这种依赖就能够在BeautifulGirl不知情的情况下替换不同的具体动作。好了我们现在明白了DI进行依关系解耦的原理了,下面我们看一下如何在Spring中应用DI。 example4实例源码下载 复制代码 复制代码 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 07:53 2018-09-27 * @Modified By: */ public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring.xml"); BeautifulGirl beautifulGirl = (BeautifulGirl) context.getBean("beautifulGirl"); beautifulGirl.action(); context.close(); } } 复制代码 这样执行Main方法,从Context中获取BeautifulGirl实例执行action方法。当然Spring提供了基于Java的配置,可作为XML配置文件的代替方案 example5实例源码下载 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 08:40 2018-09-27 * @Modified By: */ @Configuration public class SpringConfig { @Bean public SleepAction sleepAction() { return new SleepAction(); } @Bean public BeautifulGirl beautifulGirl() { return new BeautifulGirl(sleepAction()); } } 复制代码 只不过Spring的上下文的实现应该使用AnnotationConfigApplicationContext进行加载配置 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 07:53 2018-09-27 * @Modified By: */ public class Main { public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); SleepAction action = applicationContext.getBean(SleepAction.class); action.action(); } } 复制代码 3. 基于切面和惯例进行声明式编程 现在我们已经明白DI能够将互相协作的软件保持松耦合,而面向切面编程(aspect-oriented-programming,AOP)可以将遍布应用各处的功能分离出来形成可从用的组件。我们仍然使用上面的例子,BeautifulGirl随心所欲的执行各种动作真的没问题吗?如果可爱的小女孩执行的动作是去河边玩耍,吃一些危险的东西呢?那么我们势必需要一个家长(Parent类)进行监督小女孩的动作是否是安全的,下面我们来看一下Parent类。example6实例源码下载 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 09:32 2018-09-27 * @Modified By: */ public class Parent { public void check() { System.out.println("检查动作是否安全......."); } } 复制代码 非常简单!Parent(家长类)只有一个方法就是check,那么现在就让Parent对BeautifulGirl的执行动作进行检查吧。 复制代码 复制代码 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 07:44 2018-09-27 * @Modified By: */ public class BeautifulGirl implements Girl { private Action action; private Parent parent; public BeautifulGirl(Action action, Parent parent) { this.action = action; this.parent = parent; } @Override public void action() { parent.check(); action.action(); } } 复制代码 我们非常聪明,使用了DI将Parent类注入到了BeautifulGirl类中,在BeautifulGirl执行action动作之前执行 parent.check()方法,这样我们要的效果就达到了。等等....好像有什么不对的地方? 管理Parent家长的check动作真的是美丽的小女孩的职责吗? 将Parent家长注入到美丽的小女孩类中不是将代码复杂化了吗? 我们需不需要一个不需要家长注入的美丽的小女孩呢? 如果注入的Parent为NULL我们是否应该在美丽的小女孩中进行校验呢? 真的是太糟糕了,注入一个Parent(家长)将会产生那么多的问题,为什么呢?因为Parent类的业务于BeautifulGirl无关;BeautifulGirl将会承担Parent类的职责。 在一个项目中,很多系统服务都会分布到各个业务模块中,这使得业务模块的逻辑变得十分复杂,而使用AOP能够使这些服务模块化,并以声明式的方式将他们应用到他们所需要影响的组件中,使得这些组件将会具有更高的内聚性并且更加关注自身的业务逻辑,完全不需要了解系统服务所带来的复杂性。 下面我们使用SpringAOP对上面代码进行改造 example7实例源码下载 复制代码    复制代码 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 07:44 2018-09-27 * @Modified By: */ public class BeautifulGirl implements Girl { private Action action; public BeautifulGirl(Action action) { this.action = action; } @Override public void girlAction() { action.action(); } } 复制代码 我们只需要在Spring配置文件中声明Parent为Spring Bean,然后将配置在SpringAOP中即可,我们可以发现BeautifulGirl类中没有发现任何关于Parent的信息,这就是AOP的魅力所在——以声明的方式将组件应用到他们所需要影响的组件中! 4. 通过切面和模板减少样版式代码 在通过JavaAPI进行编程,我们经常会编写很多重复的代码例如JDBC访问数据库,JMS,JNDI等场景下会重复编写大量的样版式代码,而Spring皆在通过模板封装来消除模板式代码,例如Spring针对JDBC访问数据库进行封装的JdbcTemplate等,这里就是Spring使用封装的模板来减少JavaAPI样版式代码。example8实例源码下载 复制代码 /** * @Author:jimisun * @Description: * @Date:Created in 11:13 2018-09-27 * @Modified By: */ public class Main { public static void main(String[] args) { JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.execute("select * from user"); } } 复制代码 非常感谢大家耐心能看到这里,在本文中我尽可能地详细阐述Spring使如何简化Java开发?遵循哪些策略?以及为什么遵循的好处。 Java开发之上帝之眼系列教程其他文章 Java开发之上帝之眼系列教程前言和章节目录汇总 本文资料来源: 书籍 Spring IN ACTION Spring 实战 (第四版) 勘误&感谢   本系列文章资料来源很多出自于互联网和在下本身的见解,受限于个人技术能力水平和其他相关知识的限制,相关见解错误或者资料引用错误请各位帮助留言校正!引用资料多来自于互联网,在下在引用前会遵循各位前辈或者博主的引用说明表示感谢,但互联网资料多是转发再转发或存在遗漏请原作者内信联系指正。https://www.cnblogs.com/jimisun/p/9712174.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信