Spring Ioc(控制反转)以及DI(依赖注入)详解

本文详细介绍了Spring框架的核心概念,包括控制反转(IoC)和依赖注入(DI)。从Spring的起源、核心优势到体系结构,阐述了Spring在Java开发中的重要地位。接着,通过具体的入门案例,演示了IoC和DI的实现步骤,包括配置文件的编写和测试代码。文章还涵盖了Spring的核心API、Bean的实例化方式、作用域、生命周期以及依赖注入的多种方法。最后,简要回顾了Spring的学习要点,强调了注解和XML配置的混合使用。
摘要由CSDN通过智能技术生成
  • Struts2:web层,比较简单(难点:ValueStack值栈、拦截器)
  • Hibernate:dao层,知识点杂(学了不用,默认设置够用了)
  • Spring:service层,重要,(讲多少用多少)
  • Spring课程概述:
    • Spring day01:基础(IoC控制反转、DI依赖注入)、整合JUnit、整合Web
    • Spring day02:AOP切面编程、JDBCTemplate
    • Spring day03:事务管理、SSH整合

一、Spring框架概述

1.1、什么是Spring?

  • Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。该框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性可测试性松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式)轻量级开源框架。
  • 轻量级:与EJB对比,依赖资源少,消耗的资源少。
  • 分层:full-stack(一站式),每一个层都提供解决方案。
    web层:struts,spring-MVC
    service层spring
    dao层:hibernate,mybatis,jdbcTemplate –> spring-data

1.2、Spring由来(两本书)

  • 《Expert One-to-One J2EE Design and Development》
  • 《Expert One-to-One J2EE Development without EJB》

1.3、Spring核心

1.4、Spring优点

  • 方便解耦,简化开发(高内聚低耦合)
    • Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理。
    • Spring工厂就是用于生成Bean。
  • AOP编程的支持
    • Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
  • 声明式事务的支持
    • 只需要通过配置就可以完成对事务的管理,而无需手动编程。
  • 方便程序的测试
    • Spring对Junit4 支持,可以通过注解方便的测试Spring 程序。
  • 方便集成各种优秀框架
    • Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持。
  • 降低JavaEE API的使用难度
    • Spring 对JavaEE 开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。

1.5、Spring体系结构

  • Spring 框架是一个分层架构,它包含一系列的功能要素,并被分为大约20个模块。这些模块分为Core Container、Data Access/Integration、Web、AOP(Aspect Oriented Programming)、Instrumentation和测试部分,如下图所示:

二、Spring入门案例:IoC【掌握】

  • 编写流程
    • 下载Spring最新开发包
    • 复制Spring开发jar包到工程
    • 编写Spring核心配置文件
    • 在程序中读取Spring配置文件,通过Spring框架获得Bean,完成相应操作

2.1、导入jar包

4 + 1:4个核心jar包(beans、core、context、expression)+ 1个依赖jar包(com.springsource.org.apache.commons.logging-1.1.1.jar)

项目中的显示:

Spring核心开发包简介:

  • spring-core-3.2.2.RELEASE.jar
    • 包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心。
  • spring-beans-3.2.2.RELEASE.jar
    • 所有应用都要用到的,它包含访问配置文件、创建和管理bean。
    • 以及进行Inversion of Control(IoC) / Dependency Injection(DI)操作相关的所有类。
  • spring-context-3.2.2.RELEASE.jar
    • Spring提供在基础IoC功能上的扩展服务,此外还提供许多企业级服务的支持。
    • 如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等。
  • spring-expression-3.2.2.RELEASE.jar
    • Spring表达式语言。
  • com.springsource.org.apache.commons.logging-1.1.1.jar
    • 第三方的主要用于处理日志。

2.2、编写目标类

  • 创建UserService接口和实现类
  • 获得UserService实现类的实例
    • 在之前开发中,我们是直接new一个对象即可。即:private IUserDao dao = new IUserDaoImpl();
    • 在学习Spring之后,将由Spring来创建对象的实例 –> 即:IoC 控制反转(Inverse of Control)
      之后需要实例对象时,从Spring工厂(容器)中获得即可,需要将实现类的全限定名称配置到xml文件中。

UserService.java

public interface UserService {
   
    void addUser();
}

UserServiceImpl.java

public class UserServiceImpl implements UserService {
   
    @Override
    public void addUser() {
   
        System.out.println("a_ioc add user");
    }
}

2.3、编写spring配置文件

  • 位置:任意,开发中一般在classpath下(src)
  • 名称:任意,开发中常用 applicationContext.xml
  • 内容:添加schema约束
  • 约束文件位置:spring-framework-3.2.0.RELEASE\docs\spring-framework-reference\html\xsd-config.html

beans.xml

<?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 :需要创建实例的全限定类名
            注意:id的值刚开始学习的时候我们写userServiceId,在实际开发中写userService。
    -->
    <bean id="userServiceId" class="com.itheima.a_ioc.UserServiceImpl"></bean>
</beans>

2.4、测试代码

TestIoC.java

public class TestIoC {
   
    @Test
    public void demo01() {
   
        // 之前开发,自己手写new出对象
        UserService userService = new UserServiceImpl();
        userService.addUser();
    }
    @Test
    public void demo02() {
   
        // 现在从spring容器中获得对象实例
        // 1 、获得容器
        String xmlPath = "com/itheima/a_ioc/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        // 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
        UserService userService = (UserService) applicationContext.getBean("userServiceId");
        userService.addUser();
    }
}
  • IoC(Inverse of Control)反转控制的概念,就是将原本在程序中手动创建UserServiceImpl对象的控制权,交由Spring框架管理。
  • 简单说,就是创建UserServiceImpl对象的控制权被反转到了Spring框架。

三、Spring入门案例:DI【掌握】

  • DI :Dependency Injection :依赖注入
    is a :是一个,继承。
    has a:有一个,成员变量,依赖。
class B {
   
       private A a;   // B类依赖A类,B类使用A类。
    }
    依赖:一个对象需要使用另一个对象。
    注入:通过setter方法进行另一个对象实例设置。
  • 例如:
    class BookServiceImpl {
   
        // 之前开发:接口 = 实现类(service和dao耦合了,写死了,知道具体的实现类是谁,那么我的具体实现类变化,那么这行代码也得跟着变)
        // private BookDao bookDao = new BookDaoImpl();
        // spring之后(解耦:service实现类使用了dao的接口,这样就不知道具体的实现类是谁了)
        private BookDao bookDao;
        setter方法
   }
模拟spring执行过程
    创建service实例:BookService bookService = new BookServiceImpl();   => IoC <bean>
    创建dao实例:BookDao bookDao = new BookDaoImple();                  => IoC
    将dao设置给service:bookService.setBookDao(bookDao);                => DI <property>

3.1、编写目标类

  • 创建BookDao接口和实现类
  • 创建BookService接口和实现类
  • 将dao和service配置到 xml文件中
  • 使用api测试
3.1.1、dao

BookDao.java

public interface BookDao {
   
    void save();
}

BookDaoImpl.java

public class BookDaoImpl implements BookDao {
   
    @Override
    public void save() {
   
        System.out.println("b_di add book");
    }
}
3.1.2、service

BookService.java

public interface BookService {
   
    void addBook();
}

BookServiceImpl.java

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();
    }
}

代码截图如下:

3.2、编写spring配置文件


bean.xml

<?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">
    <!--  
    模拟spring执行过程
        创建service实例:BookService bookService = new BookServiceImpl();   => IoC <bean>
        创建dao实例:BookDao bookDao = new BookDaoImple();                  => IoC
        将dao实例设置给service实例:bookService.setBookDao(bookDao);         => DI <property>
        <property> 用于进行属性注入
            name : Bean的属性名称,通过setter方法获得
                setBookDao  =>  BookDao =>  bookDao
            ref :另一个Bean的id值的引用
    -->
    <!-- 创建service实例 -->                       
    <bean id="bookServiceId" class="com.itheima.b_di.BookServiceImpl">
        <!-- 将dao实例设置给service实例 --> 
        <property name="bookDao" ref="bookDaoId"></property> <!-- 用于进行属性注入 -->
    </bean>
    <!-- 创建dao实例 --> 
    <bean id="bookDaoId" class="com.itheima.b_di.BookDaoImpl"></bean>
</beans>

3.3、测试代码


TestDI.java

public class TestDI {
   
    @Test
    public void demo01() {
   
        // 之前开发,自己手写new出对象
        // BookService bookService = new BookServiceImpl();
        // bookService.addBook();
    }
    @Test
    public void demo02() {
   
        // 现在从spring容器中获得对象实例
        // 1 、获得容器
        String xmlPath = "com/itheima/b_di/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        // 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
        BookService  bookService = (BookService) applicationContext.getBean("bookServiceId");
        bookService.addBook();
    }
}
  • DI:Dependency Injection 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件。
  • getBean(“bookServiceId”); 从spring容器中获得指定名称对象的实例时,会先判断本实例对象是否需要使用其他实例化对象,由于设置了< property name=”bookDao” ref=”bookDaoId”>< /property>,说明需要使用其他实例化对象,所以就根据其他Bean的id值的引用,去spring容器中获得指定名称对象的实例,相当于将dao实例设置给service实例。

四、MyEclipse中编写applicationContext.xml时的提示设置

五、Spring的核心API(了解)

  • api整体了解即可,之后不使用,在学习过程需要。
  • BeanFactory :这是一个工厂,用于生成任意Bean。
    采取延迟加载,第一次调用getBean(); 时才会初始化Bean。(即实例化对象)
  • ApplicationContext :是BeanFactory的子接口,功能更强大。(国际化处理、事件传递、Bean自动装配、各种不同应用层的Context实现)。
    采取非延时加载,当配置文件被加载时,就进行对象的实例化。
    • ClassPathXmlApplicationContext 用于加载classpath(类路径/src)下的xml
      • 加载xml运行时位置 –> /WEB-INF/classes/xxx.xml
    • FileSystemXmlApplicationContext 用于加载指定盘符下的xml
      • 加载xml运行时位置 –> /WEB-INF/xxx.xml
      • 通过java web学习过的 ServletContext.getRealPath(); 获得具体盘符

示例代码如下:

public class TestDI {
   
    @Test
    public void demo01() {
   
        // 之前开发,自己手写new出对象
        // BookService bookService = new BookServiceImpl();
        // bookService.addBook();
    }
    @Test
    public void demo02() {
   
        // 现在从spring容器中获得对象实例,使用的是ApplicationContext
        // 1 、获得容器
        String xmlPath = "com/itheima/b_di/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); // 采取非延时加载,当配置文件被加载时,就进行对象的实例化。
        // 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
        BookService  bookService = (BookService) applicationContext.getBean("bookServiceId");
        bookService.addBook();
    }
    @Test
    public void demo03() {
   
        // 现在从spring容器中获得对象实例,使用的是BeanFactory,里面需要一个Resource,该Resource又是一个接口,需要找它的实现类ClassPathResource
        // 1 、获得容器
        String xmlPath = "com/itheima/b_di/beans.xml";
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(xmlPath));
        // 2、获得内容 ,注意此时不需要自己new出对象了,都是从spring容器中获得
        BookService  bookService = (BookService) beanFactory.getBean
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值