java spring server_Java server框架之(1):spring中的IoC
发布日期:2021-06-24 17:18:36 浏览次数:2 分类:技术文章

本文共 6810 字,大约阅读时间需要 22 分钟。

为什么需要IoC?

一般的对象耦合是在编译时确定的,也就是说当我们写如下类:

1 public classStaticCoupling {

2

3   String s = new String("hzg1981");

4

5 }

的时候,类StaticCoupling在编译期间就跟String类耦合在了一起。 在代码静态分析时,就可以确认它们之间的耦合。这种耦合使得代码的灵活性不够,因此需要一种方法对这种耦合关系进一步解耦。

什么是IoC?

IoC是Inversion of Control的缩写,翻译成中文就是控制反转。控制反转的意思就是说把对象的控制权进行转移,原来是对象A依赖对象B,那么就在A中new一个B的对象,在这种场景下,对象的控制权在对象A。实现控制反转后,对象的控制权转移到第三方,比如转移交了IoC容器。IoC容器可以理解成一个更高级的创建工厂(工厂模式):你要什么对象,它就给你什么对象,有了IoC容器,依赖关系就变了,原先的依赖关系就没了(依赖关系new没有了,对象A对象B之间的耦合也被解耦了),它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。

IoC,直观地讲,就是容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在。控制权由应用代码中转到了外部容器,控制权的转移就是所谓的反转。IoC还有另一个名字——“依赖注入(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器的运行期决定,形象的说,就是容器动态地将某种依赖关系注入到组件中。

IOC 是在运行期间才使用assembler object绑定需要耦合的对象。绑定过程是由依赖注入(DI,Dependence Injection)实现的。或者说,创建被调用者的工作由spring来完成,然后注入调用者,因此也称为依赖注入。需要注意的是IOC和DI是有区别的。IOC是一种设计范式(design paradigm),IOC是依赖于DI的,DI用来实现IOC。 DI是一种模式,用来创建对象的实例,这些实例被其他对象依赖,但是它们在编译时并不知道这些实例的类型。也就是说,DI是一种可以实现IOC的设计模式。DI不是唯一可以实现IOC的设计模式,有以下三种设计模式可以实现IOC设计范式:

1 工厂模式: factory pattern

2 服务定位器模式:service locator pattern

3 依赖注入模式。

在Spring这种IoC容器中,IoC是通过DI来实现的。依赖注入又可以分为三种类型: 构造函数注入(constructor injection)  Setter注入(setter injection)   以及接口注入(interface injection)。

构造函数注入:

1 public classDIByConstructor {2   private finalDataSource dataSource;3   private finalString message;4   publicDIByConstructor(DataSource ds, String msg) {5    this.dataSource =ds;6    ssage =msg;7 }8 ……9 }

接口注入:

1 public classClassA {2   privateInterfaceB clzB;3   publicinit() {4    Ojbect obj =Class.forName(Config.BImplementation).newInstance();5    clzB =(InterfaceB)obj;6 }7 ……8 }

Spring中的IoC,通俗的说就是可以在项目或者服务启动使用的时候,给我们一次性准备好我们程序中配置好的所需要的对象,并且自动将对象set到需要的对象中。例如A类中的成 员变量中有一个B类的引用,那么生成对象的时候会生成一个A的对象和B的对象,并且将B的对象通过A的构造方法或者set方法将B对象设置到A对象中。其实看来完成的功能很简单就是为了让我们在代码中减少使用new关键字的次数,让大多数程序中的new的性能开销和代码开销集中在项目启动或者服务启动的时候。在程序的编写过程中不会一次又一次的写A a = new A()这种没有营养的代码,在程序运行的时候不会因为多次的new对象浪费时间。

除了Spring之外,Sun ONE技术体系下的IOC容器还有:轻量级的有Guice、Pico Container、Avalon、HiveMind;重量级的有EJB;不轻不重的有JBoss,Jdon等等。Spring框架作为Java开发中 SSH(Struts、Spring、Hibernate)三剑客之一,大中小项目中都有使用,非常成熟,应用广泛,EJB在关键性的工业级项目中也被使 用,比如某些电信业务。

IoC与其他概念的关系

1 在OOD中,有一个常用的概念就是SOLID,它指的是Single Responsibility、Open-Close、L里氏替换、Independent Interface独立接口和Dependency Inversion五大OOD设计原则,这些设计原则是是设计模式的基础,设计模式的目的就是为了实现这些原则。SOLID中的D,Dependency Inversion,可以使用IoC来实现。从这个角度讲,IoC更像是一种设计模式。

2 IoC是使用反射来实现的,反射是IoC的基础。反射的应用是很广泛的,很多的成熟的框架,比如象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做为最基本的技术手段。 反射技术其实很早就出现了,但一直被忽略,没有被进一步的利用。当时的反射编程方式相对于正常的对象生成方式要慢至少得10倍。现在的反射技术经过改良优 化,已经非常成熟,反射方式生成对象和通常对象生成方式,速度已经相差不大了,大约为1-2倍的差距。

3我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语 言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

IoC的简单实现

IoC说白了就是由我们平常的new转成了使用反射来获取类的实例,相信任何人只要会用java的反射机制,那么自己写一个IOC框架也不是不可能的。

1 public ObjectgetInstance(String className) throwsException {2 Object obj =Class.forName(className).newInstance();3 Method[] methods =obj.getClass().getMethods();4 for(Method method : methods) {5 if (method.getName().intern() == "setString") {6 method.invoke(obj, "hello world!");7 }8 }9 }

上面的一个方法我们就很简单的使用了反射为指定的类的setString方法来设置一个hello world!字符串。其实可以看到IOC真的很简单,当然了IOC简单并不表示spring的IOC就简单,spring的IOC的功能强大就在于有一系列非常强大的配置文件维护类,它们可以维护spring配置文件中的各个类的关系,这才是spring的IOC真正强大的地方。在spring的Bean 定义文件中,不仅可以为定义Bean设置属性,还支持Bean之间的继承、Bean的抽象和不同的获取方式等等功能。在Spring中,对象是由IoC容器根据xml配置文件中的类名创建的,然后在应用程序需要的时候,使用构造函数注入或者其他注入方式,注入到应用程序中,从而避免了反复使用new操作创建对象。

Spring中的IoC

当前最新的Spring版本为4.3.Spring是一种IOC容器(Container),在Spring中,主要使用BeanFactory接口和ApplicationContext接口的实现类来实现IoC。客户代码甚至不需要实例化Spring的IoC容器。

BeanFactory

org.springframework.beans.factory.BeanFactory是一个接口,是Spring中的核心IOC容器接口。BeanFactory接口有若干个实现,其中最常用的实现就是XMLBeanFactory。 (XMLBeanFactory在Spring3.1中已经不鼓励使用了。替代者为 DefaultListableBeanFactory)

BeanFactory接口的主要方法为各种参数的getBean方法:

1 Object getBean(String name) throwsBeansException;2 T getBean(String name, Class requiredType) throwsBeansException;3 T getBean(Class requiredType) throws BeansException;

好像在这些getBean方法中,没有使用反射???那么,是如何实现的呢?

应用上下文 (com.springframework.context.ApplicationContext)建立在BeanFactory基础之上,提供了更多 面向应用的功能,它提供了国际化支持和框架事件体系,更易于创建实际应用。我们一般称BeanFactory为IoC容器,而称 ApplicationContext为应用上下文。但有时为了行文方便,我们也将ApplicationContext称为Spring容器。 一般而言,在构建应用程序时,我们会更多地使用ApplicationContext,而非BeanFactory。一个BeanFactory仅仅实例化并配置Java beans。一个ApplicationCongtext,不仅实例化并配置bean,还提供了针对以下多种企业特定特性的基础设施支持:事务、AOP,等。org.springframework.context.ApplicationContext

在xml配置文件中,可以配置使用不同的方式实例化Bean,可以使用静态工厂方法:

1 <?xml version="1.0" encoding="UTF-8"?>

2

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

4 xsi:schemaLocation="http://www.springframework.org/schema/beans5 http://www.springframework.org/schema/beans/spring-beans.xsd">

6

7

8

9

10

11

12

使用实例工厂方法:

1 <?xml version="1.0" encoding="UTF-8"?>

2

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

4 xsi:schemaLocation="http://www.springframework.org/schema/beans5 http://www.springframework.org/schema/beans/spring-beans.xsd">

6

7

8

9

10

11

12

13 factory-bean="speakerFactory"factory-method="newInstance" >

14

15

16

在使用Spring时经常使用如下的语句:

1 BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");

可见ApplicationContext的实现类往往也实现了BeanFactory接口。

Spring在DefaultSingletonBeanRegistry类中提供了一个用于缓存单实例Bean的缓存器,它是一个用HashMap实现的缓存器,单实例的Bean以beanName为键保存在这个HashMap中。

进一步问题

把对象生成放在配置文件里进行定义.只是把对象之间的耦合关系定义在了xml文档中,这种耦合仍在。但是对象A与B不再有耦合关系,取而代之的是对象A与IoC容器间的耦合,以及对象B与IoC容器间的耦合。

xml配置文件中的依赖,与pojo的constructor& setter不是重复信息。

Spring IoC解决了依赖具体这一问题了吗?? new SpecifcClass()是把this.Class与SpecificClass耦合在了一起,但是setter仍然保持了这种耦合关系?

still the question: what's the use of IoC compared to normal 'new' ? 是更松散的耦合吗? 意义在哪里呢? 避免多处的修改吗(多处出现new同一个bean)

运行时修改配置文件,实现更好的灵活性?

参考文献:

http://howtodoinjava.com/2013/03/19/inversion-of-control-ioc-and-dependency-injection-di-patterns-in-spring-framework-and-related-interview-questions/

http://www.informit.com/articles/article.aspx?p=174533

http://javabeginnerstutorial.com/spring-framework-tutorial/spring-aopaspect-oriented-programming/

IoC模式(in c#):  http://www.cnblogs.com/qqlin/archive/2012/10/09/2707075.html

自己动手写IoC框架:http://www.cnblogs.com/rongdi/p/4115993.html

Spring Doc:http://docs.spring.io/spring/docs/2.0.x/reference/beans.html

http://www.devshed.com/c/a/Java/The-Spring-Framework-Understanding-IoC/

http://www.springbyexample.org/examples/intro-to-ioc.html

http://www.roseindia.net/tutorial/spring/spring3/ioc/index.html

http://www.roseindia.net/tutorial/spring/spring3/ioc/springbeanexample.html

http://www.roseindia.net/tutorial/spring/spring3/ioc/springbeanexample.html

http://blog.csdn.net/cutesource/article/details/6132650

http://www.codeproject.com/Articles/465173/Dependency-Inversion-Principle-IoC-Container-Depen

http://blog.csdn.net/wanghao72214/article/details/3969594

http://www.jdon.com/dl/best/spring.htm 讲注入讲的比较清楚

转载地址:https://blog.csdn.net/weixin_34061793/article/details/114130734 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:about java_About.java
下一篇:java 多线程 临界区_【Java并发性和多线程】竞态条件与临界区

发表评论

最新留言

不错!
[***.144.177.141]2024年04月04日 00时52分13秒