【框架】[Spring3]下载安装、开源框架与IoC控制反转详解

2021-01-21 11:11:34 浏览数 (1)

转载请注明出处:http://blog.csdn.net/qq_26525215

昨天刚刚初学Spring3,也许Spring3有点老了哈,不过还是先把3学了再去学习4吧,首先先介绍一下如何去下载Spring的必须包吧。 (本篇博客适用于初学Spring的朋友)

java spring4现在不推荐使用xml配置文件… 当然啦,这些知识点在Spring4还是可以用的。

不过我在这里详解的还是Spring3哈,见谅~

下载SpringJAR包/文档:

Spring官网:http://spring.io/

Spring3.2版本以后(JAR/文档)的下载地址:http://repo.springsource.org/libs-release-local/org/springframework/spring/ (如果无法访问,请准备梯子)

选择一个需要下载的版本进去: 我选择的是最新的4.3.2版本.

spring-framework-*(版本号).RELEASE-dist.zip 包含了Spring必须的JAR包、DOC文档以及源代码等。

下载完之后解压我们就可以在spring-framework-4.3.2.RELEASElibs找到需要包和DOC文档以及源代码了。

由于最新版本的已经提倡基于Java Config和注解的配置,不采用xml配置了,所以,我在这里准备的是Spring3.1.1版本的: 下载链接: https://github.com/chenhaoxiang/Java/blob/master/Spring/spring-framework-3.1.1.RELEASE.zip

Spring开源框架

Spring框架的起始:

Spring在英语中含义就是”春天”. 对于Java EE开发者来说,Spring框架出现确实带来了一股全新的春天的气息。 早在2002年,Rod Johson在其编著的《Expert one to one J2EE design and development》书中,对Java EE框架臃肿、低效、脱离现实的种种现状提出了很多质疑,并积极寻求探索革新之道。 由他主导编写了interface21框架,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和部署的轻量级开发框架。以interface21框架为基础,并集成了其它许多开源成果,于2004年3月24日,发布了1.0正式版取名为Spring。

Spring框架模块:

Spring的核心是个轻量级容器,实现了IoC(控制翻转)模式的容器,基于此核心容器所建立的应用程序,可以达到程序组件的松散耦合。这些特性都使得整个应用程序维护简化。 Spring框架核心由下图所示的七个模块组成。

现在来分别介绍一下这七个模块:

1、核心容器(Core)

这是Spring框架最基础的部分,它提供了依赖注入(Dependency Injection)特征来实现容器对Bean的管理。这里最基本的概念是BeanFactory,它是任何Spring应用的核心。BeanFactory是工厂模式的一个实现,它使用IoC将应用配置和依赖说明从实际的应用代码中分离出来。

2、AOP模块

AOP即面向切面编程技术,Spring在它的AOP模块中提供了对面向切面编程的丰富支持。AOP允许通过分离应用的业务逻辑与系统级服务(例如安全和事务管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责其它的系统级关注点,例如日志或事务支持。

3、对象/关系映射集成模块ORM

Hibernate是成熟的ORM产品,Spring并没有自己实现ORM框架而是集成了几个流行的ORM产品如Hibernate、JDO和iBATIS等。可以利用Spring对这些模块提供事务支持等。

4、JDBC抽象和DAO模块

Spring虽然集成了几个ORM产品,但也可以不选择这几款产品,因为Spring提供了JDBC和DAO模块。该模块对现有的JDBC技术进行了优化。你可以保持你的数据库访问代码干净简洁,并且可以防止因关闭数据库资源失败而引起的问题。

[JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构管管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。SpringDAO的面向JDBC的异常遵从从通用的DAO异常层次结构]

5、Spring的Web模块

Web上下文模块建立于应用上下文模块之上,提供了一个适合于Web应用的上下文。另外,这个模块还提供了一些面向服务支持。例如:实现文件上传的multipart请求,它也提供了Spring和其它Web框架的集成,比如Struts、WebWork。

6、应用上下文(Context)模块

核心模块的BeanFactory使Spring成为一个容器,而上下文模块使它成为一个框架。Web上下文模块建立于应用上下文模块之上,提供了一个适合于Web应用的上下文。该模块还提供了一些面向服务支持这个模块扩展了BeanFactory的概念,增加了对国际化(I18N)消息、事件传播以及验证的支持。

另外,这个模块还提供了许多企业服务,例如电子邮件、JNDI访问、EJB集成、远程以及时序调度(scheduling)服务。也包括对模版框架例如Velocity和FreeMarker集成的支持。

7、Spring的MVC框架

Spring为构建Web应用提供了一个功能全面的MVC框架。虽然Spring可以很容易地与其它MVC框架集成,例如Struts2,但Spring的MVC框架使用IoC对控制逻辑和业务对象提供了完全的分离。

Spring入门示例

将需要的Jar包导入项目、

再准备一个xml配置文件: applicationContext.xml 名字不一定要这个,自己可以随意改的,但建议使用这个名字。

准备的模板:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

</beans>

将Spring的压缩包解压后:你可以在spring-framework-3.1.1.RELEASEprojectsorg.springframework.web.portletsrctestjavaorgspringframeworkwebportletcontextWEB-INF目录下找到applicationContext.xml。我们只需要这个部分就可以了。 将文件建立在src目录下(建在另外的路径也可以)。

导入必须的包,和建好applicationContext.xml文件。

1、编写一个普通的Java类(JavaBean)

代码语言:javascript复制
package cn.hncu.demo1.domain;

public class Person {
    private String name;
    private int age;

    public Person() {
        System.out.println("执行Person的构造方法....");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name="   name   ", age="   age   "]";
    }
}

2、在Spring配置文件applicationContext.xml。将JavaBean由Spring容器来管理。

代码语言:javascript复制
<beans ...>
<!--scope属性值设为:prototype(每次获取都是一个新对象), request(同一个request中获取到的是同一个), session ,不设置,默认是单例 -->
    <bean id="p" class="cn.hncu.demo1.domain.Person" scope="prototype">
    </bean>
</beans>

测试方法:

代码语言:javascript复制
    @Test
    public void demo1(){
        //此方法已在3.0版本中过时,不建议使用
        //BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

        //Spring3.0建议采用下面这种方式使用容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person p = (Person) ctx.getBean("p");//通过配置的id获得,需要强转
        System.out.println(p);

        Person p2 = ctx.getBean(Person.class);//通过Person的Class对象去获得,不需要强转
        System.out.println(p2);
    }

输出结果:

显然,Person只构造了一次。 由于我们没给初值,所以name是null,age因为是int型,所以是0.

现在我们在applicationContext.xml中来给它配置好初值,然后看:

代码语言:javascript复制
    <!--scope属性值设为:prototype(每次获取都是一个新对象), request(同一个request中获取到的是同一个), session ,不设置,默认是单例 -->
    <bean id="p" class="cn.hncu.demo1.domain.Person">
        <!-- 配置好初始值 -->
        <property name="name" value="张三"></property>
        <property name="age" value="23"></property>
    </bean>

再一次的运行结果:

演示依赖(XML)注入

在servlet注入servicce,Person, 在servicce注入dao,

LoginDAO

代码语言:javascript复制
package cn.hncu.demo1.login.dao;

import cn.hncu.demo1.domain.Person;

public interface LoginDAO {
    public void login(Person p);
}

LoginDaoJdbc

代码语言:javascript复制
package cn.hncu.demo1.login.dao;

import cn.hncu.demo1.domain.Person;

public class LoginDaoJdbc implements LoginDAO{

    @Override
    public void login(Person p) {
        System.out.println("dao,到数据库中读取用户信息以进行登录....");     
        System.out.println("dao中获取的用户输入信息:" p);     
    }

}

ILoginService

代码语言:javascript复制
package cn.hncu.demo1.login.service;

import cn.hncu.demo1.domain.Person;

public interface ILoginService {

    public void login(Person p);

}

LoginServiceImpl

代码语言:javascript复制
package cn.hncu.demo1.login.service;

import cn.hncu.demo1.domain.Person;
import cn.hncu.demo1.login.dao.LoginDAO;


public class LoginServiceImpl implements ILoginService{
    private LoginDAO dao = null;
    //如果要注入,需要注入的成员变量,必须写好set-get方法!

    public LoginDAO getDao() {
        return dao;
    }
    public void setDao(LoginDAO dao) {
        this.dao = dao;
    }

    @Override
    public void login(Person p) {
        dao.login(p);
    }

}

LoginAction

代码语言:javascript复制
package cn.hncu.demo1.login;

import cn.hncu.demo1.domain.Person;
import cn.hncu.demo1.login.service.ILoginService;

public class LoginAction {
    private ILoginService service = null;
    private Person p = null;
    //如果要注入,需要注入的成员变量,必须写好set-get方法!
    public ILoginService getService() {
        return service;
    }
    public void setService(ILoginService service) {
        this.service = service;
    }
    public Person getP() {
        return p;
    }
    public void setP(Person p) {
        this.p = p;
    }

    public void execute(){
        service.login(p);
    }

}

需要依赖注入的变量一定要写好setter-getter 方法哦!!!

测试方法:

代码语言:javascript复制
@Test//演示依赖(XML)注入
    public void demo2(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        LoginAction action = ctx.getBean(LoginAction.class);
        //LoginAction action = ctx.getBean("login",LoginAction.class);
        action.execute();
    }

配置文件:

代码语言:javascript复制
<beans ...>
<!--scope属性值设为:prototype(每次获取都是一个新对象), request(同一个request中获取到的是同一个), session ,不设置,默认是单例 -->
    <bean id="p" class="cn.hncu.demo1.domain.Person">
        <!-- 配置好初始值 -->
        <property name="name" value="张三"></property>
        <property name="age" value="23"></property>
    </bean>

    <!-- 注意这里的class是实现类,而不是接口哦 -->
    <bean id="dao" class="cn.hncu.demo1.login.dao.LoginDaoJdbc">
    </bean>

    <!-- 注意这里的class也是实现类,而不是接口哦 -->
    <!-- 如果换实现类了,只需把这里的class变了就可以了 -->
    <bean id="s" class="cn.hncu.demo1.login.service.LoginServiceImpl">
        <!-- 实现类中还有变量,ref是另外的bean的id-引用 -->
        <property name="dao" ref="dao"></property>      
    </bean>

    <bean id="login" class="cn.hncu.demo1.login.LoginAction">
        <property name="service" ref="s"></property>
        <property name="person" ref="p"></property>
    </bean>
</beans>

结构图:

运行测试方法后的输出结果:

现在增加一个DAO的实现类,可以在程序中无需代码改变,就可以注入不同实例. 我们只需要改applicationContext.xml:

代码语言:javascript复制
<!-- 注意这里的class是实现类,而不是接口哦 -->
    <!-- 如果换实现类了,只需把这里的class变了就可以了,或者不动这里,增加一个bean -->
    <bean id="dao" class="cn.hncu.demo1.login.dao.LoginDaoJdbc2">
    </bean>

增加的DAO实现类:

代码语言:javascript复制
package cn.hncu.demo1.login.dao;

import cn.hncu.demo1.domain.Person;

public class LoginDaoJdbc2 implements LoginDAO{

    @Override
    public void login(Person p) {
        System.out.println("dao2,到数据库中读取用户信息以进行登录....");        
        System.out.println("dao2中获取的用户输入信息:" p);        
    }

}

改动后的演示结果:

Spring IOC 控制反转

IoC(Inversion of Control)中文译为控制反转也可以叫做DI(Dependency Injection,依赖注入)。

控制反转模式的基本概念是:不直接创建对象,但是在xml配置文件中描述创建它们的方式。 在工程中使用该Bean时由Spring容器创建Bean的实例。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。

1、Spring注入(又称依赖注入DI):

其目的是为其中bean的属性赋值

通过Setter方法。(一般属性赋值即基本类型赋值示例)

第1步:编写JavaBean-必须写set方法

代码语言:javascript复制
package cn.hncu.demo2.domain;

public class Cat {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Cat [name="   name   "]";
    }

}

第2步: 在配置文件中注入属性的初始值

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <bean id="cat" class="cn.hncu.demo2.domain.Cat">
    <!-- 初始化name -->
        <property name="name" value="黑猫"></property>
    </bean>

</beans>

这样拿到的Cat对象就有初始值了,name的初始值为”黑猫”。

复杂数据类型的初始化:

例如,含有List,Map,Set,或者其他对象的数据,这样的bean对象如何初始化值呢。

结构如下:

Cat类就是前面那个。

User

代码语言:javascript复制
package cn.hncu.demo2.domain;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class User {
    private String name;
    private Integer age;
    private List<Object> pets;
    private Map<String, Object> map;
    private Set<Object> set;
    private Object objs[];
    private Cat cat;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }


    public List<Object> getPets() {
        return pets;
    }

    public void setPets(List<Object> pets) {
        this.pets = pets;
    }


    public Map<String, Object> getMap() {
        return map;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }



    public Set<Object> getSet() {
        return set;
    }

    public void setSet(Set<Object> set) {
        this.set = set;
    }



    public Object[] getObjs() {
        return objs;
    }

    public void setObjs(Object[] objs) {
        this.objs = objs;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    @Override
    public String toString() {
        return "User [name="   name   ", age="   age   ", pets="   pets
                  "rn map="   map   "rn set="   set   "rn objs="
                  Arrays.toString(objs)   ", cat="   cat   "]";
    }

}

配置文件

在这里我取名为:applicationContext2.xml了。

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


    <bean id="cat" class="cn.hncu.demo2.domain.Cat">
    <!-- 初始化name -->
        <property name="name" value="黑猫"></property>
    </bean>

    <bean id="user" class="cn.hncu.demo2.domain.User">
        <property name="name" value="Jack"></property>
        <property name="age" value="25"></property>

        <property name="pets">
            <list>
                <value>cat</value>
                <value>dog</value>
                <value>tiger</value>
            </list>
        </property>

        <property name="map">
            <map>
                <entry key="name" value="中国"></entry>
                <entry key="age" value="67"></entry>
                <!-- ref是引用 -->
                <entry key="cat" value-ref="cat"></entry>
            </map>
        </property>
        <property name="set">
         <set>
            <!-- 引用 -->
             <ref bean="cat"/>
             <value>aaa</value>
             <value>bbb</value>
         </set>
       </property>
        <property name="objs">
            <!-- 数组 -->
            <array>
                <value>hrllo</value>
                <ref bean="cat"/>
                <list>
                    <value>obj1</value>
                    <value>obj2</value>
                </list>
                <bean class="cn.hncu.demo2.domain.Cat">
                    <property name="name" value="白猫"></property>
                </bean>
            </array>
        </property>
    </bean>
</beans>

测试类:

代码语言:javascript复制
package cn.hncu.demo2;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.hncu.demo2.domain.User;

public class Demo2 {

    //演示spring中<bean>属性注入的一些细节
    @Test
    public void demo(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext2.xml");
        User user = ctx.getBean("user",User.class);
        System.out.println(user);
    }


}

测试结果:

如果对于这个User的类的赋值搞懂了,我想应该在这块就会很熟练了。

完整的项目源码:

https://github.com/chenhaoxiang/Java/blob/master/Spring/mySpring3Demo/mySpring3Demo.zip

本文章由[谙忆]编写, 所有权利保留。

转载请注明出处:http://blog.csdn.net/qq_26525215

0 人点赞