Spring 实例入门
本文结合实例理解解容器,DI,IOC,耦合,解耦等Spring所涉及的概念,同时了解Spring的最基本也是最核心的使用方法。
1. Spring容器
Spring容器负责对象的实例化,对象生命周期的管理,Spring管理的对象称之为Bean
例如有Soldier类需要交由Spring容器管理,我们先编写类
package com.hb;
public class Soldier {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
在Spring配置文件中添加如下配置
<bean id="s1" class="com.hb.Soldier"></bean>
初始化Spring容器
public class Test {
    public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("l");
    }
}
从Spring容器中取得对象实例
        Soldier s1 = (Soldier) Bean("s1");
Spring默认使用单例的方式创建对象。可以通过修改<bean>的配置改变成其它创建方式。这
个属性为Scope,称之为作用域或生命周期,它的值为singleton(单例,默认值),prototype(每次产生一个新的实例)等。
  <bean id="s1" class="com.hb.Soldier" scope="prototype"></bean>
2. 注入方式有setter注入,构造注入方式,接口注入(不需掌握)。建议多使用Setter注入方式。
Setter注入
Soldier类中有一个属性name,如何在创建Soldier的时候使name的值变为”RANBO”?
配置如下:
<bean  id="s1"  class="com.hb.Soldier">
<property  name="name"  value="RANBO"/>
</bean>
这样创建的Soldier对象的name属性就有值了,测试代码:
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("l");
Soldier s1 = (Soldier) Bean("s1");
System.out.Name());
}
构造注入
我们先修改下Soldier类,给它添加一个构造方法:
package com.hb;
public class Soldier {
    private String name;
    public Soldier(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
配置如下:
实例化bean的三种方式
<bean  id="s1"  class="com.hb.Soldier">
<constructor-arg  value="RANBO"></constructor-arg>
</bean>
测试结果同上。
3. 依赖
当A对象使用了B对象的方法,A对B产生依赖,称之为A依赖B。下面的例子中Soldier类依赖HandGun类。
package com.hb;
/**
* 士兵类
*/
public class Soldier {
    /**
    * 打仗
    */
    public void fight(){
        HandGun handGun = new HandGun();
        handGun.killEnemy();
    }   
}
package com.hb;
/**
* 手类
*/
public class HandGun {
    /**
    * 手杀敌
    */
    public void killEnemy(){
        System.out.println("手杀敌");
    }
}
当HandGun发生变化时,必然导致Soldier必须做相应修改,同时,当Soldier需要使用OtherGun时也必须重新编写代码,导致代码重用度不高。
当对象之间的依赖关系很强时(耦合),会使程序代码死板,不利于后期的维护和扩展。降低对象之间的依赖关系称之为解耦。Spring能够很好的解决这一问题。
4. 控制反转(Inversion of Control,简称IOC)和依赖注入(Dependence Inject简称DI)
我们运用Spring的setter注入方式解决HandGun和Soldier的耦合问题。修改Soldier的代码,将HandGun定义为Soldier的属性并提供setter方法:
package com.hb;
/**
* 士兵类
*/
public class Soldier {
    private HandGun handGun;
   
   
    public void setHandGun(HandGun handGun) {
        this.handGun = handGun;
    }
    /**
    * 打仗
    */
    public void fight(){
        handGun.killEnemy();
    }   
}
配置如下
<bean  id="s1" class="com.hb.Soldier">
<property name="handGun">
<ref bean="handgun"></ref>
</property>
</bean>
<bean id="handgun" class="com.hb.HandGun"></bean>
到这里,我们已经降低了HandGun和Soldier的部分依赖关系,至少在Soldier中不用再自己去实例化HandGun了。然而并没有彻底解决问题,Soldier中仍然可以看到HandGun类,因此我们使用接口进一步改进代码:
package com.hb;
/**
* 武器接口
*/
public interface Weapon {
    /**
    * 杀敌
    */
    void killEnemy();
}
package com.hb;
/**
* 手类
*/
public class HandGun implements Weapon{
    /**
    * 手杀敌
    */
    public void killEnemy(){
        System.out.println("手杀敌");
    }
}
package com.hb;
/**
* 士兵类
*/
public class Soldier {
    private Weapon weapon;
   
   
    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }
    /**
    * 使用武器打仗
    */
    public void fight(){
        weapon.killEnemy();
    }   
}
配置如下
<bean id="s1" class="com.hb.Soldier">
<property name="weapon">
<ref bean="handgun"></ref>
</property>
</bean>
<bean id="handgun" class="com.hb.HandGun"></bean>
测试:
ApplicationContext context = new
ClassPathXmlApplicationContext("l");
Soldier s1 = (Soldier) Bean("s1");
s1.fight();
至此,我们使用Spring很好的解决了HandGun和Soldier的耦合问题。Soldier类中再也看不到
HandGun的踪影了,Soldier只依赖于接口,而最终Soldier还是使用了HandGun,这是为什么呢?Spring在这里管理了单个的对象,也管理了对象之间即Soldier和HandGun的依赖关系。原本是由Soldier控制HandGun的实例化的,转变为由Spring容器来控制,这里发生了控制权的转移,这就是控制反转(Inversion of Control,简称IOC)。当Soldier需要HandGun时,Spring会自动将HandGun对象注入给Soldier,这就是依赖注入了。
看一下你是否已经有所领悟了:
假如“手“已经不满足“士兵”的需要,我们需要将“手”更换为更先进的“机”,你的程序如何编写呢?自己试一下吧!!
spring2.0常见异常
2009-04-06 19:50:51|  分类: Spring标签: |字号大中小 订阅
1Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory at org.springframework.util.ClassUtils.<clinit>(ClassUtils.java:67)  at io.DefaultResourceLoader.<init>(DefaultR
esourceLoader.java:52) at t.support.AbstractApplicationContext.<init>(AbstractApplicationContext.java:184) at t.support.AbstractRefreshableApplicationContext.<init>(AbstractRefreshableApplicationContext.java:80) at t.support.AbstractXmlApplicationContext.<init>(AbstractXmlApplicationContext.java:58)  at
需要加上:commons-logging.jar log4j-1.2.11.jar
2Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [l]; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
Caused by: java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException
    at java.lang.Class.forName0(Native Method)