前言

在Spring的第二篇中主要讲解了Spring Core模块的使用IOC容器创建对象的问题,Spring Core模块主要是解决对象的创建和对象之间的依赖关系,因此本博文主要讲解如何使用IOC容器来解决对象之间的依赖关系!

回顾以前对象依赖

我们来看一下我们以前关于对象依赖,是怎么的历程

直接new对象

在最开始,我们是直接new对象给service的userDao属性赋值...

class UserService{
UserDao userDao = new UserDao();
}
写DaoFactory,用字符串来维护依赖关系
后来,我们发现service层紧紧耦合了dao层。我们就写了DaoFactory,在service层只要通过字符串就能够创建对应的dao层的对象了。
DaoFactory
public class DaoFactory {
private static final DaoFactory factory = new DaoFactory();
private DaoFactory(){}
public static DaoFactory getInstance(){
return factory;
}
public T createDao(String className,Class clazz){
try{
T t = (T) Class.forName(className).newInstance();
return t;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
serivce
private CategoryDao categoryDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.CategoryDAOImpl", CategoryDao.class);
private BookDao bookDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.BookDaoImpl", BookDao.class);
private UserDao userDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.UserDaoImpl", UserDao.class);
private OrderDao orderDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.OrderDaoImpl", OrderDao.class);

DaoFactory读取配置文件

再后来,我们发现要修改Dao的实现类,还是得修改service层的源代码呀..于是我们就在DaoFactory中读取关于daoImpl的配置文件,根据配置文件来创建对象,这样一来,创建的是哪个daoImpl对service层就是透明的

DaoFactory
public class DaoFactory {
private UserDao userdao = null;
private DaoFactory(){
try{
InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
Properties prop = new Properties();
prop.load(in);
String daoClassName = prop.getProperty("userdao");
userdao = (UserDao)Class.forName(daoClassName).newInstance();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
private static final DaoFactory instance = new DaoFactory();
public static DaoFactory getInstance(){
return instance;
}
public UserDao createUserDao(){
return userdao;
}
}
service
UserDao dao = DaoFactory.getInstance().createUserDao();

Spring依赖注入

通过上面的历程,我们可以清晰地发现:对象之间的依赖关系,其实就是给对象上的属性赋值!因为对象上有其他对象的变量,因此存在了依赖...

Spring提供了好几种的方式来给属性赋值

1) 通过构造函数

2) 通过set方法给属性注入值

p名称空间

4)自动装配(了解)

5) 注解

搭建测试环境

UserService中使用userDao变量来维护与Dao层之间的依赖关系

UserAction中使用userService变量来维护与Service层之间的依赖关系

userDao
public class UserDao {
public void save() {
System.out.println("DB:保存用户");
}
}
userService
public class UserService {
private UserDao userDao;
public void save() {
userDao.save();
}
}
userAnction
public class UserAction {
private UserService userService;
public String execute() {
userService.save();
return null;
}
}

构造函数给属性赋值

其实我们在讲解创建带参数的构造函数的时候已经讲过了...我们还是来回顾一下呗..

我们测试service和dao的依赖关系就好了....在service中加入一个构造函数,参数就是userDao

public UserService(UserDao userDao) {
this.userDao = userDao;
//看看有没有拿到userDao
System.out.println(userDao);
}

applicationContext.xml配置文件

测试:可以成功获取到userDao对象

// 创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//得到service对象
UserService userService = (UserService) ac.getBean("userService");

java bufr依赖库 java中依赖_自动装配

通过set方法给属性注入值

我们这里也是测试service和dao层的依赖关系就好了...在service层通过set方法来把userDao注入到UserService中

为UserService添加set方法
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
//看看有没有拿到userDao
System.out.println(userDao);
}
public void save() {
userDao.save();
}
}

applicationContext.xml配置文件:通过property节点来给属性赋值

引用类型使用ref属性

基本类型使用value属性

测试:

java bufr依赖库 java中依赖_依赖关系_02

内部Bean

我们刚才是先创建userDao对象,再由userService对userDao对象进行引用...我们还有另一种思维:先创建userService,发现userService需要userDao的属性,再创建userDao...我们来看看这种思维方式是怎么配置的:

applicationContext.xml配置文件:property节点内置bean节点

测试

java bufr依赖库 java中依赖_java bufr依赖库_03

我们发现这种思维方式和服务器访问的执行顺序是一样的,但是如果userDao要多次被其他service使用的话,就要多次配置了...

p 名称空间注入属性值

p名称控件这种方式其实就是set方法的一种优化,优化了配置而已...p名称空间这个内容需要在Spring3版本以上才能使用...我们来看看:

applicationContext.xml配置文件:使用p名称空间

测试

java bufr依赖库 java中依赖_java bufr依赖库_04

自动装配

Spring还提供了自动装配的功能,能够非常简化我们的配置

自动装载默认是不打开的,自动装配常用的可分为两种:

根据名字来装配

根据类型类装配

XML配置根据名字

applicationContext.xml配置文件:使用自动装配,根据名字

测试

java bufr依赖库 java中依赖_spring_05

XML配置根据类型

applicationContext.xml配置文件:使用自动装配,根据类型

值得注意的是:如果使用了根据类型来自动装配,那么在IOC容器中只能有一个这样的类型,否则就会报错!

测试:

java bufr依赖库 java中依赖_spring_06

我们这只是测试两个对象之间的依赖关系,如果我们有很多对象,我们也可以使用默认自动分配

java bufr依赖库 java中依赖_spring_07

###使用注解来实现自动装配###

@Autowired注解来实现自动装配:

可以在构造器上修饰

也可以在setter方法上修饰

来自java的@Inject的和@AutoWired有相同的功能

如果没有匹配到bean,又为了避免异常的出现,我们可以使用required属性上设置为false。【谨慎对待】

测试代码

@Component
public class UserService {
private UserDao userDao ;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}

顺利拿到userDao的引用

java bufr依赖库 java中依赖_依赖关系_08

使用JavaConfig配置类实现对象依赖

在有两种方法(但我测试不出来,如果会的请在评论去告诉我.....)

第一种(测试不出来)

import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class Configuration {
@Bean()
public UserDao userDao() {
return new UserDao();
}
@Bean
public UserService userService() {
//直接调用@bean的方法
return new UserService(userDao());
}
}
第二种(测试不出来)
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class Configuration {
@Bean()
public UserDao userDao() {
return new UserDao();
}
@Bean
public UserService userService(UserDao userDao) {
//通过构造函数依赖注入
return new UserService(userDao);
}
}

java bufr依赖库 java中依赖_spring_09

如果我直接通过构造器传入的话,那么报错了

import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class Configuration {
@Bean()
public UserDao userDao() {
return new UserDao();
}
@Bean(autowire = Autowire.BY_TYPE)
public UserService userService(UserDao userDao) {
return new UserService(userDao);
}
}

java bufr依赖库 java中依赖_java bufr依赖库_10

我测试中只有通过这种方法才能拿到userDao的引用。

public class Configuration {
@Bean()
public UserDao userDao() {
return new UserDao();
}
@Bean(autowire = Autowire.BY_TYPE)
public UserService userService() {
return new UserService(userDao());
}
}

java bufr依赖库 java中依赖_spring_11

当然了,最简单直观的方法还有一种:在UserService中加入setUser()方法,那么只要set进去就行了..

UserService
public class UserService {
private UserDao userDao ;
public UserService() {
}
public UserService(UserDao userDao) {
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
Config
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class Config1 {
@Bean(name = "userDao")
public UserDao userDao() {
return new UserDao();
}
@Bean(name="userService")
public UserService userService() {
UserService userService = new UserService();
userService.setUserDao(userDao());
return userService;
}
}

java bufr依赖库 java中依赖_java依赖注入_12