Spring核心之IoC——依赖注入

时间:2024-01-12 17:28:38

在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());
}
}

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

Spring核心之IoC——依赖注入

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的属性值
}
}

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

Spring核心之IoC——依赖注入

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的基本用法