用Spring来实现IOC
在上节中我们自定义了一个接口BeanFactory和类ClassPathXmlApplicationContext来模拟Spring,其实它们在Spring中确实是存在的,下面我们具体来看看Spring的控制反转是如何操作的
其他代码一样,只是配置文件和单元测试的代码有点不同,注意引用其他bean配置的是"ref"属性
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl">
</bean>
<bean id="userService" class="com.bjsxt.service.UserService">
<property name="userDAO" ref="u" /> </bean> </beans>
配置文件
package com.bjsxt.service;
import org.junit.Test; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource; import com.bjsxt.model.User; //Dependency Injection
//Inverse of Control
public class UserServiceTest { @Test
public void testAdd() throws Exception {
BeanFactory ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService"); User u = new User();
u.setUsername("zhangsan");
u.setPassword("zhangsan");
service.add(u);
} }
测试代码
注:ClassPathXmlApplicationContext继承ApplicationContext,ApplicationContext又继承BeanFactory,所以也可以这样写ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");推荐使用这种写法。其构造函数也可以传入String数组,适用于多个配置文件的情况
三种注入方式(setter,构造函数,接口)
setter已经见过了,接口注入很少用,故此忽略,下面来看一下构造函数注入,在UserService中添加一个构造函数初始化UserDAO属性
package com.bjsxt.service;
import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User; public class UserService { private UserDAO userDAO; public void add(User user) {
userDAO.save(user);
}
public UserDAO getUserDAO() {
return userDAO;
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
} public UserService(UserDAO userDAO) {
super();
this.userDAO = userDAO;
}
}
添加构造函数的UserService
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl">
</bean> <bean id="userService" class="com.bjsxt.service.UserService">
<!--
<property name="userDAO" ref="u" />
-->
<constructor-arg>
<ref bean="u"/>
</constructor-arg>
</bean> </beans>
配置文件
注意用的是constructor-arg标签,如果构造函数有多个参数,就按照顺序写,或者指定index
Bean的Scope属性
配置文件中bean有个scope属性,如果配置为singleton,表示该bean只有一个实例,如果配置为prototype,每次取出该bean都会创建一个新的对象。bean的scope属性配置为singleton和prototype,在下面的代码中会分别输出true和false
package com.bjsxt.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.bjsxt.model.User; //Dependency Injection
//Inverse of Control
public class UserServiceTest { @Test
public void testAdd() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService");
UserService service2 = (UserService)ctx.getBean("userService"); System.out.println(service == service2); User u = new User();
u.setUsername("zhangsan");
u.setPassword("zhangsan");
service.add(u);
} }
UserService测试scope属性