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