热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring学习(一)——Spring中的依赖注入简介

【前面的话】Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spr

【前面的话】

     Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring。不知道为什么对Spring有一种莫名的喜欢感,也许是因为他的名字,有一种希望的感觉。

    Spring学习过程中的总结和心得,本文介绍了在初次学习Spring的时候,对于依赖注入的理解,希望有时间可以进行更深入的学习。请选择性阅读。

本文由牲口TT在博客园首次发表,转载请保持文章的完整性并注明:
作者:牲口TT
链接:http://www.cnblogs.com/xt0810/p/3593853.html

Spring介绍】

     Spring Framework 是一个开源的Java/Java EE全功能栈(full-stack)的应用程序框架,以Apache许可证形式发布,也有.NET平台上的移植版本。该框架基于 Expert One-on-One Java EE Design and Development(ISBN 0-7645-4385-7)一书中的代码,最初由 Rod Johnson 和 Juergen Hoeller等开发。Spring Framework 提供了一个简易的开发方式,这种开发方式,将避免那些可能致使底层代码变得繁杂混乱的大量的属性文件和帮助类。

     控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

【依赖注入】

     在学习Spring的时候,总是会遇到这个名词,就是依赖注入,所以首先学习什么是依赖注入。通过几个例子,说明什么是依赖注入,什么是spring下的依赖注入。

     我们举一个Person开car的例子,希望通过这个例子可以更好的学习和理解什么是依赖注入。当然举得例子都是很简单的情形,在实际项目中可能要比这些复杂的多。

一、第一种情形:紧耦合情形,开宝马。

1. 分析如下:

     定义三个类,Person.java、BaoMa.java、MainTest.java。如下面的代码,Person在它的构造函数中创建了Baoma对象,这就让Person类和Baoma类紧密的耦合在了一起,而且现在Person类只能开宝马,如果现在想要开奥迪,Person类是不能够处理的,除非修改Person这个类,这就使得两个类在紧耦合的情况下逻辑变得不够清晰,如果业务逻辑复杂,这些紧耦合的情形就会更多,带来代码难以测试,难以复用,难以理解等很多弊端。再加上让Person类来管理Baoma类的对象创建也是不合理的,因为面向对象的思想来说,Person类是没有管理Baoma类的对象的职责的。

2. 代码如下:

1)Person.java

 1 public class Person {
 2     private BaoMa baoma;
 3     public Person(){
 4         baoma=new BaoMa();//Person和Baoma这个类紧耦合
 5     }
 6     public void driver(){
 7         baoma.GuaDang();
 8         baoma.CaiYouMen();
 9         baoma.DaFangXiang();
10     }
11 }

2)BaoMa.java 

public class BaoMa {
    public void GuaDang(){
        System.out.println("我是宝马车,我在进行挂档");
    }
    public void CaiYouMen(){
        System.out.println("我是宝马车,我在进行踩油门");
    }
    public void DaFangXiang(){
        System.out.println("我是宝马车,我在进行打方向盘");
    }
}

3)MainTest.java

public class MainTest {
     public static void main(String[] args){
        Person boy =new Person();
        boy.driver();
    }
}

3.  运行结果:

我是宝马车,我在进行挂档
我是宝马车,我在进行踩油门
我是宝马车,我在进行打方向盘

二、第一种情形:紧耦合情形,开奥迪。

 1.  分析如下:

      从上面的代码中,我们如果想要开奥迪,只能对Person类进行修改,依次类推,如果开车人每次想要开的车不同,就需要每次对于Person类进行修改,这对于Person类来说是不合理的,Person类只关心我要开车,我有一个driver方法,我每次想要开车就是调用driver方法,所以这种紧耦合的编码是不够理想的。

2.  代码如下:

1)  Person.java

 1 public class Person {
 2     private AuDi audi;
 3     public Person(){
 4         audi=new AuDi();
 5     }
 6     public void driver(){
 7         audi.GuaDang();
 8         audi.CaiYouMen();
 9         audi.DaFangXiang();
10     }
11 }

2)   AuDi.java

 1 public class AuDi {
 2     public void GuaDang(){
 3         System.out.println("我是奥迪车,我在进行挂档");
 4     }
 5     public void CaiYouMen(){
 6         System.out.println("我是奥迪车,我在进行踩油门");
 7     }
 8     public void DaFangXiang(){
 9         System.out.println("我是奥迪车,我在进行打方向盘");
10     }
11 }

3)   MainTest.java

1 public class MainTest {
2      public static void main(String[] args){
3         Person boy =new Person();
4         boy.driver();
5     }
6 }

3.  运行结果:

1 我是奥迪车,我在进行挂档
2 我是奥迪车,我在进行踩油门
3 我是奥迪车,我在进行打方向盘

三、第二种情形:简单的依赖注入情形。

1.  分析如下:

     在java的设计思想中,依赖注入的核心思想就是这种具体类之间的依赖,尽量转换成抽象依赖,也就是如下代码一样,Person类的依赖于抽象的Car类,而不是具体的Baoma类或者具体的AuDi类,分析见代码注释。

2.  代码如下:

1) Person.java

 1 public class Person {
 2     private Car car;
 3     public Person(Car car){//构造器注入,传入的是car,也就是一个所有车型都必须实现的接口
 4         this.car =car;//这里可以响应奥迪,宝马等任何一种车的实现。
 5     }//这里Person类没有与任何特定类型的车发生耦合,对于Person来说,任何一种特定的车,只需要实现Car接口即可。具体是哪一种车型,对Person来说无关紧要。
 6     public void driver(){
 7         car.GuaDang();
 8         car.CaiYouMen();
 9         car.DaFangXiang();
10     }
11 }

2)  Car.java

1 public interface Car {
2     public abstract void GuaDang();
3     public abstract void CaiYouMen();
4     public abstract void DaFangXiang();
5 }

3)  AuDi.java

 1 public class AuDi implements Car {
 2     public void GuaDang(){
 3         System.out.println("我是奥迪车,我在进行挂档");
 4     }
 5     public void CaiYouMen(){
 6         System.out.println("我是奥迪车,我在进行踩油门");
 7     }
 8     public void DaFangXiang(){
 9         System.out.println("我是奥迪车,我在进行打方向盘");
10     }
11 }

4)  MainTest.java

1 public class MainTest {
2      public static void main(String[] args){
3         AuDi audi=new AuDi();
4         Person boy =new Person(audi);
5         boy.driver();
6     }
7 }

3.  运行结果:

1 我是奥迪车,我在进行挂档
2 我是奥迪车,我在进行踩油门
3 我是奥迪车,我在进行打方向盘

四、第三种情形:Spring的依赖注入情形。

1.  分析如下:

     通过上面的说明,现在对于依赖注入应该有一个较好的理解了,那么Spring是如何实现IOC的?

     通过依赖注入,对象的依赖关系将由负责协调系统中各个对象的第三方组件在创建对象时设定。对象无需自行创建或管理它们的依赖关系——依赖关系将自动注入到需要它们的对像中去。Spring就是这样的第三方组件,通过使用Spring框架,使得类之间的依赖关系通过Spring来进行管理。

     具体的Spring进行依赖注入的方式和方法有时间在进行学习总结,今天只是对于Spring依赖注入的理解学习。

2.  代码如下:

1)Person.java

 1 public class Person {
 2     private Car car;
 3     public Person(Car car){//构造器注入,传入的是car,也就是一个所有车型都必须实现的接口
 4         this.car =car;//这里可以响应奥迪,宝马等任何一种车的实现。
 5     }//这里Person类没有与任何特定类型的车发生耦合,对于Person来说,任何一种特定的车,只需要实现Car接口即可。具体是哪一种车型,对Person来说无关紧要。
 6     public void driver(){
 7         car.GuaDang();
 8         car.CaiYouMen();
 9         car.DaFangXiang();
10     }
11 }

2) Car.java

1 public interface Car {
2     public abstract void GuaDang();
3     public abstract void CaiYouMen();
4     public abstract void DaFangXiang();
5 }

3) AuDi.java

 1 public class AuDi implements Car {
 2     public void GuaDang(){
 3         System.out.println("我是奥迪车,我在进行挂档");
 4     }
 5     public void CaiYouMen(){
 6         System.out.println("我是奥迪车,我在进行踩油门");
 7     }
 8     public void DaFangXiang(){
 9         System.out.println("我是奥迪车,我在进行打方向盘");
10     }
11 
12 }

4) cartest.xml

 1 xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:p="http://www.springframework.org/schema/p"
 5     xmlns:context="http://www.springframework.org/schema/context"
 6     xsi:schemaLocation="http://www.springframework.org/schema/beans
 7         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 8         http://www.springframework.org/schema/context
 9         http://www.springframework.org/schema/context/spring-context-3.0.xsd">    
10     <bean id="cartest" class="Person">
11         <constructor-arg ref="Car" />
12     bean>
13     <bean id="Car" class="AuDi" />
14 beans>

5)MainTest.java

1 import org.springframework.context.ApplicationContext;
2 import org.springframework.context.support.ClassPathXmlApplicationContext;
3 public class MainTest {
4      public static void main(String[] args){
5          ApplicationContext cOntext= new ClassPathXmlApplicationContext("cartest.xml");
6          Person boy =(Person) context.getBean("cartest");
7          boy.driver();
8      }
9 }

3.  运行结果:

1 我是奥迪车,我在进行挂档
2 我是奥迪车,我在进行踩油门
3 我是奥迪车,我在进行打方向盘

【注意问题】

    在编写上面的第四中的代码,需要注意一些问题,对于新手来说,可能会遇到错误。在这里说明一下:

一、首先需要导入如下的jar包。

  1. org.springframework.context-3.0.2.RELEASE.jar(点击可下载)
  2. org.springframework.beans-3.0.2.RELEASE.jar(点击可下载)
  3. org.springframework.core-3.0.2.RELEASE.jar(点击可下载)
  4. commons-logging-1.0.4.jar(点击可下载)
  5. org.springframework.asm-3.0.1.RELEASE-A.jar(点击可下载)
  6. org.springframework.expression-3.0.1.RELEASE-A.jar(点击可下载)

二、代码的结构如下图:

红线的地方在同一目录下。

三、可能遇到的错误

1. 错误:

The type org.springframework.core.NestedRuntimeException cannot be resolved. It is indirectly referenced from required .class files

解决办法:

导入:org.springframework.core-3.0.2.RELEASE

2.  错误:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

解决办法:

导入:commons-logging-1.0.4

3.  错误:

Caused by: java.lang.ClassNotFoundException: org.springframework.asm.ClassVisitor

解决办法:

导入:org.springframework.asm-3.0.1.RELEASE-A

4.  错误:

org.springframework.expression.PropertyAccessor

解决办法:

导入:org.springframework.expression-3.0.1.RELEASE-A

【参考资料】

1. 《Spring in action》 Craig Walls著 耿渊 张卫滨译

【后面的话】

    总是想学习很多东西,但是每次都不能够很好的完成的时候,或多或少总是很失望,我要好好学习。

分享:

     1.读书,读到倦,网上有很多方法,但你从来沉不下心看。
     2.学习,学到疼,网上有很多方法,但你从来沉不下心看。
     3.开口说话,冷场也要说话,脸皮薄也要说话,挨打也要说话。
     4.如果你现在不知道做什么,至少你还可以先从做一个牛逼的学生开始。
     5.更漂亮更有趣的女孩,五年以后再找。
     6.承诺是鞭子,不是兴奋剂。
     7.年纪大了,也不要说什么心如死灰。

——TT

 


推荐阅读
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有