您的位置:首页 > 编程语言 > Java开发

Spring 之IOC和DI

2018-01-14 17:17 309 查看
原来在开发中,创建对象时总是利用关键字new实例化一个对象。通过主动实例化创建对象。这样导致很多对象无法被回收,并且如果类之间有依赖关系,就会有很高的耦合度。下面给出原来的实现方式。

@Test
public void demo01(){
//变为面向接口编程
UserService userService = new UserServiceImpl();
userService.addUser();
}


1.IOC

如果需要修改UserService 的实现类,那么demo01的代码内容也要修改。软件开发的原则低耦合,所以想办法依靠配置文件动态给出完整类名,然后利用反射机制生成对象。这就是IOC(控制反转)即手动创建类交给Spring完成。

<?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.xsd"> <!-- 配置service
<bean> 配置需要创建的对象
id :用于之后从spring容器获得实例时使用的
class :需要创建实例的全限定类名
-->
<bean id="userService" class="com.IOCtest1.UserServiceImpl"></bean>
</beans>


@Test
public void demo02(){
//从spring容器获得
//1 获得容器
String xmlPath = "com/IOCtest1/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
//2获得内容 --不需要自己new,都是从spring容器获得
UserService userService = (UserService) applicationContext.getBean("userService");
userService.addUser();

}




不同的业务代码和具体实现类之间通过IOC容器关联。大大地降低耦合度。

2.DI

如果存在类间依赖,一个类的对象作为另外一个类的属性来用。

这里BookServiceImpl需要调用BookDao 的一个方法,使用set注入。

public class BookServiceImpl implements BookService {

// 方式1:之前,接口=实现类
//  private BookDao bookDao = new BookDaoImpl();
// 方式2:接口 + setter
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}

@Override
public void addBook(){
this.bookDao.save();
}

public BookServiceImpl() {
System.out.println("BookService被创建了");
}

}


配置文件

<?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.xsd"> 
<bean id="bookService" class="com.Ditest1.service.BookServiceImpl">
// 联系起来
<property name="bookDao" ref="bookDao"></property>
</bean>
<bean id="bookDao" class="com.Ditest1.dao.BookDaoImpl"></bean>
</beans>


<property>
用于进行属性注入

name: bean的属性名,通过setter方法获得

ref :依赖的bean的id值的引用

class则是告诉IOC这个类的完全限定名称

测试用例

@Test
public void test02(){
String xmlPath="com/Ditest/applicationContext.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
BookService bookService=(BookService) applicationContext.getBean("bookService");
bookService.addBook();
}


Spring IOC 使用完整思路:

我们利用xml配置文件(properties文件也可以)对bean进行声明和管理,每个bean代表将要被创建的对象,并通过property与其他类或属性联系。这样Spring容器可以知道我们要创建bean实例。

然后在Java代码中利用ClassPathXmlApplicationContext加载配置文件,生成实例对象。完成相应功能代码。

//默认查找classpath路径下的文件
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring/spring-ioc.xml")
//默认为项目工作路径 即项目的根目录
FileSystemXmlApplicationContext applicationContext=
new FileSystemXmlApplicationContext("/src/main/resources/spring/spring-ioc.xml");


3. Spring 依赖注入(DI)的方式

1.构造器注入

设置带参数的构造函数。spring容器会根据bean中指定的构造方法参数来决定调用那个构造方法。

xml配置文件:

<!-- 通过构造注入依赖 -->
<bean name="accountService" class="com.springIoc.service.impl.UserServiceImpl">
<!-- 构造方法方式注入userDao对象,-->
<constructor-arg  ref="userDao"/>
</bean>
<bean name="userDao" class="com.springIoc.dao.impl.UserDaoImpl"/>


public class UserServiceImpl implements UserService{
/**
* 需要注入的对象Dao层对象
*/
private UserDao userDao;

/**
* 构造注入
* @param
*/
public UserServiceImpl(UserDao userDao){
this.userDao=userDao;
}
//........
}


2.set方式注入

类中属性变量设置Setter()方法。

上面的例子就是使用的set方式注入。

3.自动装配

default-autowire=”no/default/constructor|byType|byname” //全局注释

autowire=”no/default/constructor|byType|byname”

“在byTpye模式中,Spring容器会基于反射查看bean定义的类,然后找到与依赖类型相同的bean注入到另外的bean中,这个过程需要借助setter注入来完成,因此必须存在set方法,否则注入失败”

同样byName模式的自动装配,此时Spring只会尝试将属性名与bean名称进行匹配,如果找到则注入依赖bean。

对于constructor模式,在该模式下Spring容器同样会尝试找到那些类型与构造函数相同匹配的bean然后注入。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  IOC DI