2021-09-17 Spring5_IoC和DI笔记

Spring5 IoC和DI

1 Spring 简介

1.1 Spring是什么

Spring : 春天 —>给软件行业带来了春天

2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架。

2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版。

很难想象Rod Johnson的学历 , 他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。

Spring理念 : 使现有技术更加实用 . 本身就是一个大杂烩 , 整合现有的框架技术

官网 : http://spring.io/

官方下载地址 : https://repo.spring.io/libs-release-local/org/springframework/spring/

GitHub : https://github.com/spring-projects

1.2 Spring的优点

1、Spring是一个开源免费的框架 , 容器 .

2、Spring是一个轻量级的框架 , 非侵入式的 .

3、控制反转 IoC(方便解耦,简化开发) , 面向切面 AOP

4、对事务的支持 , 对框架的支持

5、方便程序的测试

6、方便集成各种优秀框架

7、降低JavaEE API的使用难度

8、

一句话概括:

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。

1.3 Spring的体系结构

在这里插入图片描述
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

核心容器(Core Container):核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。

Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

1.4 拓展

Spring Boot与Spring Cloud

Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务;

Spring Cloud是基于Spring Boot实现的;

Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;

Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置 , Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。

SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。

2 Spring快速入门

2.1 Spring程序开发步骤

  • ① 导入 Spring 开发的基本包坐标

    • <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.0.5.RELEASE</version>
      </dependency>
      
  • ② 编写 Dao 接口和实现类

    • 接口

      • package com.raphuscucullatus.dao;
        
        /**
         * spring快速开始
         *
         * @author raphus cucullatus
         * @version 2021/9/1718:24
         * @since JDK8
         */
        public interface UserDao    {
            /**
             * 快速开始测试方法接口
             */
            void save();
        }
        
    • 实现类

      • package com.raphuscucullatus.dao.impl;
        
        import com.raphuscucullatus.dao.UserDao;
        
        /**
         * @author raphus cucullatus
         * @version 2021/9/17 18:25
         * @since JDK8
         */
        public class UserDaoImpl implements UserDao {
        
            @Override
            public void save() {
                System.out.println("save running....");
            }
        }
        
  • ③ 在resources目录下创建 Spring 核心配置文件 applicationContext.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">
      
          <bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl"></bean>
      
      </beans>
      
  • ④ 使用 Spring 的 API 获得 Bean 实例

    • package com.raphuscucullatus.dao;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      /**
       * UserDaoImpl的测试类
       *
       * @author raphus cucullatus
       * @version 2021/9/17 18:38
       * @since JDK8
       */
      public class UserDaoImplTest {
          @Test
          public void testSave(){
              ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
              UserDao userDao = (UserDao)app.getBean("userDao");
              userDao.save();
          }
      }
      

3 Spring配置文件

3.1 配置详解

<!--
id: Bean实例的唯一性标识
class: Bean的全限定名
scope: 对象的作用范围,取值如下:
    singleton 默认值,单例的(默认) 
		Bean的实例化时机:Spring核心配置被加载时创建1个实例
		Bean的生命周期:容器创建时创建,容器销毁时销毁(类似静态对象)
    prototype 多例的
		Bean的实例化时机:每次调用getBean方法是时创建1个实例
		Bean的生命周期:与getBean方法获取对象同时创建 销毁
		
    WEB 项目中
        request  Spring创建一个 Bean 的对象,将对象存入到 request 域中
        session  Spring创建一个 Bean 的对象,将对象存入到 session 域中
        global session  应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当
        于 session
-->
    <bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl"></bean>
@Test
public void testScope(){
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    //scope="singleton" userDao的地址:UserDaoImpl@7b8b43c7 userDao2的地址:UserDaoImpl@7b8b43c7
    //scope="prototype" userDao的地址:UserDaoImpl@4278284b userDao2的地址:UserDaoImpl@9573584
    UserDao userDao = (UserDao)app.getBean("userDao");
    UserDao userDao2 = (UserDao)app.getBean("userDao");
    System.out.println("userDao的地址:"+userDao);
    System.out.println("userDao2的地址:"+userDao2);
}
配置获取实例的方式
<!--  获取实例方法一  -->
<bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl" scope="singleton"
init-method="init" destroy-method="destroy"></bean>
<!--  (了解)获取实例方法二:工厂静态方法  -->
<bean id="userDao" class="com.raphuscucullatus.factory.StaticFactory" factory-method="getUserDao"></bean>
<!--  (了解)获取实例方法三:工厂实例态方法  -->
<bean id="factory" class="com.raphuscucullatus.factory.Factory"></bean>
<bean id="userDao" factory-bean="factory" factory-method="getUserDao"/>
依赖注入(Depandency Injection)

方式一:构造方法

spring核心配置文件

<bean id="userService" class="com.raphuscucullatus.service.impl.UserServiceImpl">
    <constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>

Dao层

package com.raphuscucullatus.dao.impl;

import com.raphuscucullatus.dao.UserDao;

/**
 * @author raphus cucullatus
 * @version 2021/9/17 18:25
 * @since JDK8
 */
public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {
        System.out.println("UserDaoImpl无参构造创建实例");
    }

    public void init (){
        System.out.println("UserDaoImpl初始化");
    }
    public void destroy (){
        System.out.println("UserDaoImpl被销毁");
    }

    @Override
    public void save() {
        System.out.println("save running....");
    }
}

服务层

/**
 * UserService实现类
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:42
 * @since JDK8
 */
public class UserServiceImpl implements UserService {
    private UserDao userDao;
    //仅有此处代码与set注入时有区别
    public UserServiceImpl() {
    }
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void save() {
        userDao.save();
    }
}

在控制层进行测试

package com.raphuscucullatus.controller;

import com.raphuscucullatus.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试控制层
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:51
 * @since JDK8
 */
public class UserController {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService)app.getBean("userService");
        userService.save();
    }
}

方式二:set方法

spring核心配置文件

  • 使用property子标签配置依赖注入
<bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl" scope="singleton"
      init-method="init" destroy-method="destroy"></bean>
<!--    给UserServiceImpl注入相应的依赖    -->
<bean id="userService" class="com.raphuscucullatus.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
</bean>
  • 或使用p命名空间配置依赖注入(了解)

    首先在跟标签beans属性中引入p命名空间,如下

xmlns:p="http://www.springframework.org/schema/p"

​ 之后即可在bean标签中可通过p:userDao-ref属性配置依赖注入

<bean id="userService" class="com.raphuscucullatus.service.impl.UserServiceImpl" p:userDao-ref="userDao"></bean>

Dao层

package com.raphuscucullatus.dao.impl;

import com.raphuscucullatus.dao.UserDao;

/**
 * @author raphus cucullatus
 * @version 2021/9/17 18:25
 * @since JDK8
 */
public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {
        System.out.println("UserDaoImpl无参构造创建实例");
    }

    public void init (){
        System.out.println("UserDaoImpl初始化");
    }
    public void destroy (){
        System.out.println("UserDaoImpl被销毁");
    }

    @Override
    public void save() {
        System.out.println("save running....");
    }
}

服务层

/**
 * UserService实现类
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:42
 * @since JDK8
 */
public class UserServiceImpl implements UserService {
    private UserDao userDao;
	//仅有此处代码与构造器注入有区别
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }
    @Override
    public void save() {
        userDao.save();
    }
}

在控制层进行测试

package com.raphuscucullatus.controller;

import com.raphuscucullatus.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试控制层
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:51
 * @since JDK8
 */
public class UserController {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService)app.getBean("userService");
        userService.save();
    }
}
可注入的数据类型

除了引用Bean的注入, 普通数据类型,集合等都可以在容器中注入

配置文件:

<bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl" scope="singleton"
      init-method="init" destroy-method="destroy">
    <!--
        注入UserDaoImpl成员变量
            字符串
            基本数据类
            List
            Map
            properties
    -->
    <property name="userName" value="张三"/>
    <property name="age" value="18"/>
    <property name="userNameList">
        <list>
            <value>狗蛋</value>
            <value>李四</value>
            <value>王五</value>
        </list>
    </property>
    <property name="userMap">
        <map>
            <!--value的值为自定义类User-->
            <entry key="狗蛋" value-ref="狗蛋"></entry>
            <entry key="李四" value-ref="李四"></entry>
            <entry key="王五" value-ref="王五"></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="手机号">15159044077</prop>
            <prop key="邮箱">15511u5@qq.com</prop>
        </props>
    </property>
</bean>
<!--自定义类User-->
<bean id="狗蛋" class="com.raphuscucullatus.bean.User">
    <property name="name" value="狗蛋"></property>
    <property name="age" value="34"></property>
</bean>
<bean id="李四" class="com.raphuscucullatus.bean.User">
    <property name="name" value="李四"></property>
    <property name="age" value="24"></property>
</bean>
<bean id="王五" class="com.raphuscucullatus.bean.User">
    <property name="name" value="王五"></property>
    <property name="age" value="15"></property>
</bean>

自定义类User:

package com.raphuscucullatus.bean;

/**
 * 用户实体
 *
 * @author raphus cucullatus
 * @version 2021/9/17 22:20
 * @since JDK8
 */
public class User {
    /**
     * 用户名
     */
    private String name;
    /**
     * 用户的年龄
     */
    private int age;
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

userDaoImpl

package com.raphuscucullatus.dao.impl;

import com.raphuscucullatus.bean.User;
import com.raphuscucullatus.dao.UserDao;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author raphus cucullatus
 * @version 2021/9/17 18:25
 * @since JDK8
 */
public class UserDaoImpl implements UserDao {
    /**
     * 用户名
     */
    private String userName;
    /**
     * 用户的年龄
     */
    private int age;

    private List<String> userNameList;
    private Map<String, User> userMap;
    private Properties properties;


    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setUserNameList(List<String> userNameList) {
        this.userNameList = userNameList;
    }

    public void setUserMap(Map<String, User> userMap) {
        this.userMap = userMap;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public UserDaoImpl() {
        System.out.println("UserDaoImpl无参构造创建实例");
    }

    public void init (){
        System.out.println("UserDaoImpl初始化");
    }
    public void destroy (){
        System.out.println("UserDaoImpl被销毁");
    }

    @Override
    public void save() {
        System.out.println("用户名:"+userName+",年龄:"+age);
        System.out.println(userNameList);
        System.out.println(userMap);
        System.out.println(properties);
        System.out.println("save running....");

    }
}

在控制层进行测试

package com.raphuscucullatus.controller;

import com.raphuscucullatus.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试控制层
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:51
 * @since JDK8
 */
public class UserControllerTest {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService)app.getBean("userService");
        userService.save();
    }
}

3.2 引入其他配置文件

实际开发中, Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载

<import resource="applicationContext-user.xml"/>

例如将注入自定义类User的配置单独放入applicationContext-user.xml文件中,在原配置文件中引入此配置即可:

<bean id="userDao" class="com.raphuscucullatus.dao.impl.UserDaoImpl" scope="singleton"
      init-method="init" destroy-method="destroy">
    <!--
        注入UserDaoImpl成员变量
            字符串
            基本数据类
            List
            Map
            properties
    -->
    <property name="userName" value="张三"/>
    <property name="age" value="18"/>
    <property name="userNameList">
        <list>
            <value>狗蛋</value>
            <value>李四</value>
            <value>王五</value>
        </list>
    </property>
    <property name="userMap">
        <map>
            <!--value的值为自定义类User-->
            <entry key="狗蛋" value-ref="狗蛋"></entry>
            <entry key="李四" value-ref="李四"></entry>
            <entry key="王五" value-ref="王五"></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="手机号">15159044077</prop>
            <prop key="邮箱">15511u5@qq.com</prop>
        </props>
    </property>
</bean>
<import resource="applicationContext-user.xml"/>

applicationContext-user.xml文件中配置

<!--自定义类User-->
<bean id="狗蛋" class="com.raphuscucullatus.bean.User">
    <property name="name" value="狗蛋"></property>
    <property name="age" value="34"></property>
</bean>
<bean id="李四" class="com.raphuscucullatus.bean.User">
    <property name="name" value="李四"></property>
    <property name="age" value="24"></property>
</bean>
<bean id="王五" class="com.raphuscucullatus.bean.User">
    <property name="name" value="王五"></property>
    <property name="age" value="15"></property>
</bean>

这样配置不会影响程序运行结果.

4 Spring相关API

4.1 Spring继承体系

在这里插入图片描述

4.2 ApplicationContext的实现类

1) ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件 推荐使用这种
2) FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
3) AnnotationConfigApplicationContext
使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

package com.raphuscucullatus.controller;

import com.raphuscucullatus.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * 测试控制层
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:51
 * @since JDK8
 */
public class UserControllerTest {
    public static void main(String[] args) {
        //从**类的根路径**下加载配置文件
//        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从**磁盘路径**上加载配置文件
        ApplicationContext app = new FileSystemXmlApplicationContext("D:\\JavaDevelop\\IDE\\workspace\\spring\\spring_ioc\\src\\main\\resources\\applicationContext.xml");

        UserService userService = (UserService)app.getBean("userService");
        userService.save();
    }
}

4.3 getBean方法的使用

package com.raphuscucullatus.controller;

import com.raphuscucullatus.bean.User;
import com.raphuscucullatus.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * 测试控制层
 *
 * @author raphus cucullatus
 * @version 2021/9/17 20:51
 * @since JDK8
 */
public class UserControllerTest {
    public static void main(String[] args) {
        //从**类的根路径**下加载配置文件
//        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从**磁盘路径**上加载配置文件
        ApplicationContext app = new FileSystemXmlApplicationContext("D:\\JavaDevelop\\IDE\\workspace\\spring\\spring_ioc\\src\\main\\resources\\applicationContext.xml");

        //通过id获取
//        UserService userService = (UserService)app.getBean("userService");
        //通过类名.class获取
        UserService userService = app.getBean(UserService.class);
        userService.save();
//        通过类名.class获取时,且配置中有多个时该类对象时抛出NoUniqueBeanDefinitionException
//        User user = app.getBean(User.class);
//        System.out.println(user);

    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值