spring IOC 概念理解

spring IOC 概念理解

spring 概念理解(资料)
一、Spring的IoC(Inversion of Control)。

这是Spring中得有特点的一部份。IoC又被翻译成“控制反转”,也不知道是谁翻译得这么别扭,感觉很深奥的词。其实,原理很简单,用一句通俗的话来说:就是用XML来定义生成的对象。IoC其实是一种设计模式,Spring只是实现了这种设计模式。

这种设计模式是怎么来的呢?是实践中逐渐形成的。

第一阶段:用普通的无模式来写Java程序。一般初学者都要经过这个阶段。

第二阶段:频繁的开始使用接口,这时,接口一般都会伴随着使用工厂模式。

第三阶段:使用IoC模式。工厂模式还不够好:(1)因为的类的生成代码写死在程序里,如果你要换一个子类,就要修改工厂方法。(2)一个接口常常意味着一个生成工厂,会多出很多工厂类。

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

    IoC中最基本的Java技术就是“反射”编程。反射又是一个生涩的名词,通俗的说反射就是根据给出的类名(字符串)来生成对象。这种编程方式可以让对象在生成时才决定要生成哪一种对象。我在最近的一个项目也用到了反射,当时是给出一个.properties文本文件,里面写了一些全类名(包名+类名),然后,要根据这些全类名在程序中生成它们的对象。反射的应用是很广泛的,象Hibernate、String中都是用“反射”做为最基本的技术手段。

    在过去,反射编程方式相对于正常的对象生成方式要慢10几倍,这也许也是当时为什么反射技术没有普通应用开来的原因。但经SUN改良优化后,反射方式生成对象和通常对象生成方式,速度已经相差不大了(但依然有一倍以上的差距)。

    所以要理解IoC,你必须先了解工厂模式和反射编程,否则对它产生的前因后果和实现原理都是无法理解透彻的。只要你理解了这一点,你自己也完全可以自己在程序中实现一个IoC框架,只不是这还要涉及到XML解析等其他知识,稍微麻烦一些。

    IoC最大的好处是什么?因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单(一般这样的对象都是现实于某种接口的),只要修改XML就可以了,这样我们甚至可以实现对象的热插拨(有点象USB接口和SCIS硬盘了)。

    IoC最大的缺点是什么?(1)生成一个对象的步骤变复杂了(其实上操作上还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。(2)对象生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。(3)缺少IDE重构操作的支持,如果在Eclipse要对类改名,那么你还需要去XML文件里手工去改了,这似乎是所有XML方式的缺憾所在。

    总的来说IoC无论原理和实现都还算是很简单的。一些人曾认为IoC没什么实际作用,这种说法是可以理解的,因为如果你在编程中很少使用接口,或很少使用工厂模式,那么你根本就没有使用IoC的强烈需要,也不会体会到IoC可贵之处。有些人也说要消除工厂模式、单例模式,但是都语焉不详、人云亦云。但如果你看到IoC模式和用上Spring,那么工厂模式和单例模式的确基本上可以不用了。但它消失了吗?没有!Spring的IoC实现本身就是一个大工厂,其中也包含了单例对象生成方式,只要用一个设置就可以让对象生成由普通方式变单一实例方式,非常之简单。

   总结:

   (1)IoC原理很简单,作用的针对性也很强,不要把它看得很玄乎。

   (2)要理解IoC,首先要了解“工厂、接口、反射”这些概念。

二、Spring中IOC的实现

了解了IOC模式的思想以及其优点,再来学习其实现。上面大致描述了PicoContainer以及Spring各自对IOC的实现,这篇来详细看一下Spring中它的实现。

Spring中IOC贯穿了其整个框架,但正如martinflower所说:“saying that these lightweight containers are special because they use inversion of control is like saying my car is special because it has wheels”,IOC已经称为框架设计中必不可少的部分。就实现上来讲Spring采取了配置文件的形式来实现依赖的注射,并且支持Type2 IOC(Setter Injection)以及Type3 IOC(Constructor Injection)。

Spring中IOC的实现的核心是其Core Bean Factory,它将框架内部的组件以一定的耦合度组装起来,并对使用它的应用提供一种面向服务的编程模式(SOP:Service-Orient Programming),比如Spring中的AOP、以及持久化(Hibernate、ibatics)的实现。

    首先从最底层最基础的factory Bean开始,先来看org.springframework.beans.factory.Bean

Factory接口,它是一个非常简单的接口,getBean方法是其中最重要的方法,Spring通常是使用xml来populate Bean,所以比较常用的是XMLFactoryBean。

用一个简单的示例看一下其用法。首先写下两个Bean类:

ExampleBean 类:

public class ExampleBean {

       private String psnName=null;

       private RefBean refbean=null;

       private String addinfo=null;

       public String getAddinfo() {

              return getRefbean().getAddress()+getRefbean().getZipcode();

       }

       public String getPsnName() {

              return psnName;

       }

       public void setPsnName(String psnName) {

              this.psnName = psnName;

       }

       public void setRefbean(RefBean refbean) {

              this.refbean = refbean;

       }

       public RefBean getRefbean() {

              return refbean;

       }

       public void setAddinfo(String addinfo) {

              this.addinfo = addinfo;

       }

}

RefBean类:

public class RefBean {

       public String getAddress() {

              return address;

       }

       public void setAddress(String address) {

              this.address = address;

       }

       public String getZipcode() {

              return zipcode;

       }

       public void setZipcode(String zipcode) {

              this.zipcode = zipcode;

       }

       private String zipcode=null;

       private String address=null;

}

其xml配置文件 Bean.xml 

<?xml version=”1.0″ encoding=”UTF-8″?>

<!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN”

“http://www.springframework.org/dtd/spring-beans.dtd”>

<beans>

  <bean id=”exampleBean” class=”test.ExampleBean”>

    <property name=”psnName”><value>xkf</value></property>

    <property name=”refbean”>

       <ref bean=”refBean”/>

    </property>

  </bean>

  <bean id=”refBean” class=”test.RefBean”>

  <property name=”address”><value>BeiJing</value></property>

  <property name=”zipcode”><value>100085</value></property>

  </bean>

</beans>

然后可以写个测试类来测试,当然,需要Spring中的Spring-core.jar以及commons-logging.jar,当然在elipse中可以通过安装spring-ide插件来轻松实现。

public class Test {

       public static void main(String[] args){

              try{

              Resource input = new ClassPathResource(“test/Bean.xml”);

              System.out.println(“resource is:”+input);

              BeanFactory factory = new XmlBeanFactory(input);

              ExampleBean eb =

              (ExampleBean)factory.getBean(“exampleBean”);

              System.out.println(eb.getPsnName());

              System.out.println(eb.getAddinfo());

       }

       catch(Exception e){

              e.printStackTrace();

       }

}

这样,通过BeanFactory的getBean方法,以及xml配置文件,避免了在test类中直接实例化ExampleBean,消除了应用程序(Test)与服务(ExampleBean)之间的耦合,实现了IOC(控制反转)或者说实现了依赖的注射(Dependency Injection)。

“>”refbean”>

       <ref bean=”refBean”/>

    </property>

  </bean>

  <bean id=”refBean” class=”test.RefBean”>

  <property name=”address”><value>BeiJing</value></property>

  <property name=”zipcode”><value>100085</value></property>

  </bean>

</beans>

然后可以写个测试类来测试,当然,需要Spring中的Spring-core.jar以及commons-logging.jar,当然在elipse中可以通过安装spring-ide插件来轻松实现。

public class Test {

       public static void main(String[] args){

              try{

              Resource input = new ClassPathResource(“test/Bean.xml”);

              System.out.println(“resource is:”+input);

              BeanFactory factory = new XmlBeanFactory(input);

              ExampleBean eb =

              (ExampleBean)factory.getBean(“exampleBean”);

              System.out.println(eb.getPsnName());

              System.out.println(eb.getAddinfo());

       }

       catch(Exception e){

              e.printStackTrace();

       }

}

这样,通过BeanFactory的getBean方法,以及xml配置文件,避免了在test类中直接实例化ExampleBean,消除了应用程序(Test)与服务(ExampleBean)之间的耦合,实现了IOC(控制反转)或者说实现了依赖的注射(Dependency Injection)。


出处:
http://www.zhuoda.org/xiaoming/66303.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/100465.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 斗鱼主播都在使用的可取回的CSGO开箱子网站推荐!「建议收藏」

    斗鱼主播都在使用的可取回的CSGO开箱子网站推荐!「建议收藏」斗鱼主播都在使用的可取回的CSGO开箱子网站推荐!incsgo能直接取回皮肤的CSGO饰品皮肤开箱网站官方链接:www.incsgo.gg注册登录自动免费获得$1.00美金优惠码:csgogo(充值使用csgogo可增加5%充值金额)支付:微信支付宝状态:直接取回skinsdog狗网CSGO饰品皮肤开箱网站可直接取回官方链接:skinsdog.cc注册登录自动免费获得$0.8美金推广码:csgogo(注册使用送0.8美金)支付:微信支付宝状态:直.

    2022年10月4日
    3
  • kafka消息和日志

    kafka消息和日志

    2021年9月15日
    62
  • Java核心技术卷一学习笔记1

    Java核心技术卷一学习笔记1在搞本科生毕设之余,闲下来看看书,写写博客。由于研究生学习要做一个数据可视化的项目,需要用到Java。所以拿了一本《Java核心技术卷一》正在一步步复习之前所学的Java知识。   3.9大数值   如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中的两个很有用的类:BigInteger和BigDecimal。这两个类可以处理包含任意长度数字序列的数值。

    2025年8月7日
    2
  • unity touch事件_安卓开发按钮点击事件

    unity touch事件_安卓开发按钮点击事件一:下面先说经常用的三个事件手指按下、手指移动、手指松开1.手指按下if(input.touchCount==1){if(input.touches[0].phase==TouchPhase.Beagn){//手指按下时,要触发的代码}​​​​​​​2.手指在屏幕上滑动if(input.touchCount==1)if(input.t

    2025年10月18日
    2
  • AD域、Windows AD域管理功能大全「建议收藏」

    AD域、Windows AD域管理功能大全「建议收藏」WindowsAD域管理功能大全,再也不用东拼西凑了!功能一、AD域管理1、AD域管理通过批量创建和编辑用户帐户,指派管理权限等,简化WindowsAD域的管理。2、批量管理域用户使用CSV文件批量导入用户、编辑用户属性、重置密码、批量迁移用户和用户对象。3、批量创建域用户通过导入CSV文件,批量创建用户,包含Exchange邮箱、终端服务等所有属性,指派到组。4、批…

    2022年5月17日
    29
  • Dreamweaver 2020安装教程[通俗易懂]

    Dreamweaver 2020安装教程[通俗易懂]装前先关闭杀毒软件和360卫士,注意安装路径不能有中文,安装包路径也不要有中文。1.鼠标右击【Dreamweaver2020】压缩包选择【解压到Dreamweaver2020】。2.双击打开解压后的【Dreamweaver2020】文件夹。3.双击打开【setup】文件夹。4.鼠标右击【Set-up】选择【以管理员身份运行】。5.点击【继续】。6.点击文件夹图标,然后点击【更改位置】更改安装路径。7.建议安装在除…

    2022年5月25日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号