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、Spring中都是用“反射”做为最基本的技术手段。

    在过去,反射编程方式相对于正常的对象生成方式要慢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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值