Spring核心之IoC——依赖注入

在J2EE开发平台中,Spring是一种优秀的轻量级企业应用解决方案。Spring倡导一切从实际出发,它的核心技术就是IOC(控制反转)和AOP(面向切面编程)技术。本文用的Spring版本为spring-framework-2.5.6(通过Myeclipse导入),不同版本的jar包可能会存在不同的区别。

Spring内置了日志组件log4j.jar,所以在正式使用Spring之前需要对log4j进行简单的配置,在项目的src根目录下创建log4j.properties属性文件。具体代码如下:

#输出级别,输出错误信息,输出源为标准输出源stdout
log4j.rootLogger=WARN,stdout
#将stdout输出到控制台中
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#日志输出的布局类 log4j.appender.stdout.layout
=org.apache.log4j.PatternLayout
#指定日志输出内容的格式 log4j.appender.stdout.layout.ConversionPattern
=%d %p [%c] -%m %n

 

依赖注入

IoC,即控制反转。开发者在使用类的实例之前,需要先创建对象的实例。但是IoC将创建实例的任务交给IoC容器,这样开发应用代码时只需要直接使用类的实例,这就是IoC。在讨论控制反转这个概念的过程中,Martin Fowler提出了一个更为准确的概念,叫做依赖注入(Dependency Injection)。

1. Setter注入

例1.1 通过Spring的赋值为用户JavaBean的属性赋值。

(1)首先创建用户的JavaBean,关键代码如下:

package com.cn.gao;

public class User {
    private String name;
    private Integer age;
    private String sex;
    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 String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
}

(2)在Spring的配置文件applicationContext.xml中配置该JavaBean。关键代码如下:

<?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-2.5.xsd">
    <!-- User Bean -->
    <bean name="user" class="com.cn.gao.User">
        <property name="name">
            <value>小强</value>
        </property>
        <property name="age">
            <value>26</value>
        </property>
        <property name="sex">
            <value></value>
        </property>
    </bean>

</beans>

说明:如果当JavaBean的某个属性是List集合类型或数组时,需要使用<list>标签为List集合类型或数组的每一个元素赋值。

(3)创建类Manger,在其main()方法中的关键代码如下:

package com.cn.gao;

import org.springframework.core.io.Resource;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class Manger {
    public static void main(String[] args) {
        Resource resource =new ClassPathResource("applicationContext.xml");  //装载配置文件
        BeanFactory factory = new XmlBeanFactory(resource);
        User user = (User)factory.getBean("user");  //获取bean
        System.out.println("用户姓名————"+user.getName());
        System.out.println("用户年龄————"+user.getAge());
        System.out.println("用户性别————"+user.getSex());
    }
}

程序运行后,在控制台输出的信息如下图所示:

 

2. 构造器注入

在类被实例化时,它的构造方法被调用并且只能调用一次。所以构造器常被用于类的初始化操作。<constructor-arg>是<bean>元素的子元素。通过<constructor-arg>元素的<value>子元素可以为构造方法传参。

例2.1 通过Spring的构造器注入为用户JavaBean的属性赋值。

(1)在用户JavaBean中创建构造方法,关键代码如下:

package com.cn.gao;

public class User {
    private String name;
    private Integer age;
    private String sex;
    //构造方法
    public User(String name,Integer age,String sex){
        this.name=name;
        this.age=age;
        this.sex=sex;
    }
    //输出JavaBean的属性值方法
    public void printInfo(){
        System.out.println("用户姓名——"+name);
        System.out.println("用户年龄——"+age);
        System.out.println("用户性别——"+sex);
    }
}

(2)在Spring的配置文件applicationContext.xml中通过<constructor-arg>元素为JavaBean的属性赋值。

<?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-2.5.xsd">
    <!-- User Bean -->
    <!-- 
    <bean name="user" class="com.cn.gao.User">
        <property name="name">
            <value>小强</value>
        </property>
        <property name="age">
            <value>26</value>
        </property>
        <property name="sex">
            <value>男</value>
        </property>
    </bean>
     -->

    <!-- User Bean -->
    <bean name="user" class="com.cn.gao.User">
        <constructor-arg>
            <value>小强</value>
        </constructor-arg>
        <constructor-arg>
            <value>26</value>
        </constructor-arg>
        <constructor-arg>
            <value></value>
        </constructor-arg>
    </bean>
</beans>

注意:容器中通过多个<constructor-arg>标签完成了对构造方法的传参,但是如果标签的赋值顺序与构造方法中参数的顺序或参数类型不同,程序会产生异常。可以使用

<constructor-arg>元素的index属性和type属性解决此类问题。

说明:(1)index属性:用于指定构造方法的参数索引,指定当前<constructor-arg>标签为构造方法的哪个参数赋值。

   (2)type属性:可以指定参数类型以确定要为构造方法的哪个参数赋值,当需要赋值的属性在构造方法中没有相同的类型时,可以使用这个参数。

(3)创建类Manger,在其main()方法中的关键代码如下:

package com.cn.gao;

import org.springframework.core.io.Resource;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class Manger {
    public static void main(String[] args) {
        Resource resource =new ClassPathResource("applicationContext.xml");  //装载配置文件
        BeanFactory factory = new XmlBeanFactory(resource);
        User user = (User)factory.getBean("user");  //获取bean
//        System.out.println("用户姓名————"+user.getName());
//        System.out.println("用户年龄————"+user.getAge());
//        System.out.println("用户性别————"+user.getSex());
        user.printInfo();    //输出JavaBean的属性值
    }
}

程序运行后,在控制台输出的信息如下图所示:

3. 引用其他的bean

Spring利用IoC将JavaBean所需要的属性注入到其中,不需要编写程序代码来初始化JavaBean的属性,使程序代码整洁、规范化。最主要的是它降低了JavaBean之间的耦合度,Spring开发项目中的JavaBean不需要任何修改就可以应用到其它程序中。在Spring中可以通过配置文件使用<ref>元素引用其他JavaBean的实例对象。

例3.1 将User对象注入到Spring的控制器Manger1中,并在控制器中执行User的printInfo()方法。

(1)在控制器Manger1中注入User对象,关键代码如下:

package com.cn.gao;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

public class Manger1 extends AbstractController {
    private User user;            //注入User对象
    public User getUser(){
        return user;
    }
    
    public void setUser(User user){
        this.user=user;
    }
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
            HttpServletResponse arg1) throws Exception {
        user.printInfo();  //执行User中的信息打印方法
        return null;
    }

}

说明:如果在控制器中返回的是一个ModelAndView对象,那么该对象需要在Spring的配置文件applicationContext.xml中进行配置。

(2)在Spring的配置文件applicationContext.xml中设置JavaBean的注入,关键代码如下:

    <!-- 注入JavaBean -->
    <bean name="/main.do" class="com.cn.gao.Manger1">
        <property name="user">
            <ref bean="user"/>
        </property>
    </bean>

(3)在web.xml文件中配置自动加载applicationContext.xml文件,在项目启动时,Spring的配置信息将自动加载到程序中,所以在调用JavaBean时不再需要实例化BeanFactory对象。

 

<?xml version="1.0" encoding="GBK"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>java_spring</display-name>
  <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>
  
  <!-- 设置自动加载配置文件 -->
  <servlet>
      <servlet-name>dispatcherServlet</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/applicationContext.xml</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>dispatcherServlet</servlet-name>
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

Spring3系列5-Bean的基本用法

 

posted @ 2015-05-03 13:13  ~风轻云淡~  阅读(1721)  评论(1编辑  收藏  举报