Spring笔记(一)——xml方式实现IoC和DI

来源:互联网 发布:产品网站源码 编辑:程序博客网 时间:2024/06/06 00:51

javaweb开发中,几乎离不开各种开源框架的支持。
javaweb的开发分为三个层次:

  • WEB层 (表现层)

  • 业务层 – Bean管理:(IOC)

  • 持久层 – Spring的JDBC模板.ORM模板用于整合其他的持久层框架
    在这三个层次中,常用的框架结构有SSH和SSM。无论是SSH还是SSM,业务层都是由Spring来实现的。因此,Spring框架对于javaweb开发非常重要。

    1.Spring简介

  • Spring是一个开源框架
  • Spring是于2003 年兴起的一个轻量级的Java开发框架,由Rod Johnson在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。
  • 它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。
  • Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以 从Spring中受益。

1.1 Spring的特点

* 方便解耦,简化开发    * Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理* AOP编程的支持    * Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能* 声明式事务的支持    * 只需要通过配置就可以完成对事务的管理,而无需手动编程* 方便程序的测试    * Spring对Junit4支持,可以通过注解方便的测试Spring程序* 方便集成各种优秀框架    * Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持* 降低JavaEE API的使用难度    * Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

2.Spring之IoC技术简介

IoC(Inverse of Control),控制反转,将对象的创建权反转给Spring,解决程序耦合性高的问题。
平常的开发中,我们创建一个对象,必须使用new这个关键词来完成。在javaweb的三层开发结构中,三个不同的层次的类之间进行调用。如果都使用new这个关键字来创建对象的实例。那么程序的耦合性会非常高,后期维护会很麻烦。
Spring的IoC技术,帮开发者创建和管理对象。只需要在配置文件中引入先关类的全路径,那么Spring会通过反射来帮助我们创建对象。我们不需要new对象,便可以安安心心的使用了。

2.1 需要导入的jar包

这里写图片描述
具体的jar包可以去spring的官网或者一些开源社区上去下载。其中第一个包是日志的jar包。

3. 代码实现IoC

创建两个测试类,一个是service层的类,一个是dao层的类。service层测类调用dao层的类。一般开发中,这两个类最好各自实现自己的接口,方便解耦。

public class MydaoImpl implements Mydao {    public void save() {    System.out.println("这里是持久层");    }}
public class MyServiceImpl implements MyService {    private MydaoImpl myDao;    private String name;    private int age;    private ArrayList<String> list;    public void setList(ArrayList<String> list) {        this.list = list;    }    public void setName(String name) {        this.name = name;    }    public void setAge(int age) {        this.age = age;    }    public void setMyDao(MydaoImpl myDao) {        this.myDao = myDao;    }    @Override    public void saveUser() {        System.out.println("业务层保存用户");    }    public void printInfo(){        System.out.println("age-"+age+"name-"+name);    }    public void testDI(){        myDao.save();    }    public void printList(){        for (String str : list) {            System.out.println(str);        }    }}

3.1 spring实现IoC的配置文件

<?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:p="http://www.springframework.org/schema/p"    xsi:schemaLocation="        http://www.springframework.org/schema/beans         http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="myservice" class="com.mq.service.MyServiceImpl"></bean></beans>

该xml的名称为applicationContext.xml,名称可以改,但一般都为applicationContext。一般放在src目录下。

每一个需要被管理的类,放在在bean标签中进行配置,class是该类的全路径。id是给该类设置一个唯一的标志。

3.2 测试

public class MyTest {    @Test    public void f1(){         // 使用Spring的工厂:        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");        // 通过工厂获得类:        MyServiceImpl userService = (MyServiceImpl) applicationContext.getBean("myservice");        userService.saveUser();    }}

测试结果:

11:49:19,413  INFO ClassPathXmlApplicationContext:578 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@46f5f779: startup date [Fri Jul 14 11:49:19 CST 2017]; root of context hierarchy11:49:19,464  INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [applicationContext.xml]业务层保存用户

在调用MyServiceImpl的saveUser方法中,没有创建MyServiceImpl的实例,就可以直接调用该方法了。因为Spring已经帮我们创建了该类的实例对象。
这就是一个最简单的Spring实现IoC的例子。

4. DI

DI ( Dependency Injection),依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中!!

最常见的场景是,A类需要调用B类的方法,B类是A类的成员属性。并且要提供set方法。首先A类和B类都必须在applicationContext.xml配置文件中进行配置。
MyServiceImpl有三个属性,其中myDao是一个类的引用。这种形式在开发中非常常见。具体代码上面已经给出。

4.1 依赖注入的配置文件

<?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:p="http://www.springframework.org/schema/p"    xsi:schemaLocation="        http://www.springframework.org/schema/beans         http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="myservice" class="com.mq.service.MyServiceImpl"><property name="name" value="张三"/><property name="age" value="15"/><property name="myDao" ref="mydao"></property></bean><bean id="mydao" class="com.mq.dao.MydaoImpl"></bean></beans>

对于MydaoImpl和MyServiceImpl都进行了配置。在bean标签下,有property子标签,该标签就是用来配置依赖注入的。

property标签中,name表示在该类中的属性名称,该值必须和MyServiceImpl的属性一致。value表示给该属性赋值,如果该属性是基础类型或者String类型的话。ref表示引用。后面必须是另外一个已经配置的类的id值。
简而言之,在property标签中,name表示属性。如果属性是包括String类型在内的基础类型,使用value直接进行赋值。如果是该属性是其他类的引用,那么就使用ref

测试结果:

public class MyTest {    @Test    public void f1(){         // 使用Spring的工厂:        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");        // 通过工厂获得类:        MyServiceImpl userService = (MyServiceImpl) applicationContext.getBean("myservice");        //userService.saveUser();        userService.printInfo();        userService.testDI();    }}
12:12:09,241  INFO ClassPathXmlApplicationContext:578 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@52d455b8: startup date [Fri Jul 14 12:12:09 CST 2017]; root of context hierarchy12:12:09,287  INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [applicationContext.xml]age-15name-张三这里是持久层

可见,MyServiceImpl中,我们没有new MyDaoImpl的实例对象,就可以调用MyDaoImpl的方法。

4.2 构造方法注入

这种方式用到的不是特别多,需要提供构造方法。

            public class Fruit {                private String name;                private double money;                public Fruit (String name, double money) {                    this.name = name;                    this.money = money;                }            }

依赖注入的配置文件内容:

<bean id="fruit" class="com.mq.bean.Fruit">                <constructor-arg name="name" value="香蕉"/>                <constructor-arg name="money" value="100"/>            </bean>

4.3数组集合和Properties的注入

以list集合为例,在MyServiceImpl中声明list属性,并且提供set方法。
配置文件中:

<bean id="myservice" class="com.mq.service.MyServiceImpl"><property name="name" value="张三"/><property name="age" value="15"/><property name="myDao" ref="mydao"></property>        <property name="list">            <list>                <value>吃饭</value>                <value>睡觉</value>            </list>        </property></bean>

其中, 中的内容,就是赋给集合中的元素。

4.3.1 其他集合的注入方式
2. 如果是Set集合,注入的配置文件方式如下:    <property name="set">        <set>            <value>上班</value>            <value>下班</value>        </set>    </property>3. 如果是Map集合,注入的配置方式如下:    <property name="map">        <map>            <entry key="香蕉" value="3.8"/>            <entry key="橘子" value="2"/>            <entry key="苹果" value="1"/>        </map>    </property>4. 如果是properties属性文件的方式,注入的配置如下:    <property name="pro">        <props>            <prop key="name">root</prop>            <prop key="password">test</prop>        </props>    </property>

5. Spring的其他标签的配置

bean标签中,除了最为常见的id和class子标签,还有其他标签。

  • name:给Bean起个名字。如果没有设置id标签,name可以当做id来使用。
  • scope:代表Bean的作用范围。有五个取值。
    * singleton         -- 单例(默认值)。    * prototype         -- 多例,整合Struts2中,Action类是多例的,必须设置此属性。    * request           -- 应用在Web项目中,每次HTTP请求都会创建一个新的Bean    * session           -- 应用在Web项目中,同一个HTTP Session 共享一个Bean    * globalsession     -- 应用在Web项目中,多服务器间的session
  • init-method:创建bean时调用init-method指定的方法
  • destroy-method:销毁该bean的实例事调用其指定的方法。

6. 其他

目前都只是在测试的方法中加载applicationContext.xml文件。每执行一次测试的方法,都需要重新加载配置文件,效率会比较低。
在web开发中,也不建议来一次请求,就先加载applicationContext.xml文件,再执行相应的方法。这样效率会非常低。
最好的方法时,在ServletContext创建的时候就加载该配置文件,不用每次请求来了都去加载。因此,需要一个listener进行监听ServletContext的创建。

第一步:首先需要导入spring-web-4.2.4.RELEASE.jar包。
第二步:配置监听器:

<!-- 配置Spring的核心监听器: -->         <listener>            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>         </listener>         <context-param>            <param-name>contextConfigLocation</param-name>            <param-value>classpath:applicationContext.xml</param-value>         </context-param>

第三步:在请求的方法中使用Bean

WebApplicationContext applicationContext =WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());        MyServiceImpl myservice= (MyServiceImpl) applicationContext.getBean("myservice")        myservice.testDI();

这样,只有在项目启动的时候才会加载配置文件,我们直接在web层的接收请求的方法中,可以通过applicationContext对象直接获取相应的bean对象。

原创粉丝点击