Spring 之IOC和DI

原来在开发中,创建对象时总是利用关键字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然后注入。

发布了137 篇原创文章 · 获赞 123 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/lz20120808/article/details/79056685