SSM笔记(1)Spring——IoC和DI

Spring—IoC和DI

  • 1. Spring简介
    • 1.1 Spring概述
    • 1.2 Spring的体系结构
  • 2. Spring 快速入门
    • 2.1 Spring程序的开发步骤
  • 3. Spring配置文件
    • 3.1 bean标签的基本配置
    • 3.2 bean标签范围配置
    • 3.3 bean生命周期配置
    • 3.4 bean实例化三种方式
    • 3.5 bean的依赖注入入门
    • 3.6 bean的依赖注入方式
    • 3.7 bean的依赖注入的数据类型
      • 1) 普通数据类型的注入
      • 2) 集合数据类型的注入
    • 3.8 引入其他配置文件(分模块开发)
  • 4. Spring相关API
    • 4.1 ApplicationContext的实现类
    • 4.2 getBean()方法使用

1. Spring简介

1.1 Spring概述

Spring是一个IOC(DI)AOP容器开源框架,为简化企业级开发而生,使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理,这样使得很多复杂的代码在Spring中开发却变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。
Spring的优良特性:

  • 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API
  • 控制反转:IOC——Inversion of Control,指的是将对象的创建权交给Spring去创建。使用Spring之前,对象的创建都是由我们自己在代码中new创建。而使用Spring之后。对象的创建都是由给了Spring框架。
  • 依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用setXX方法去设置,而是通过配置赋值。
  • 面向切面编程:Aspect Oriented Programming——AOP
  • 容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
  • 组件化:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
  • 一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)。

1.2 Spring的体系结构

SSM笔记(1)Spring——IoC和DI_第1张图片

2. Spring 快速入门

以前手动new对象的开发方式:
SSM笔记(1)Spring——IoC和DI_第2张图片
现在Spring的开发方式:
SSM笔记(1)Spring——IoC和DI_第3张图片

2.1 Spring程序的开发步骤

2.1.1 导入 Spring 开发的基本包坐标
pom.xml中配置Spring依赖

 <dependencies>
     <dependency>
         <groupId>org.springframeworkgroupId>
         <artifactId>spring-contextartifactId>
         <version>5.0.5.RELEASEversion>
     dependency>
 dependencies>

2.1.2 编写Dao接口和实现类
接口:UserDao.java

public interface UserDao {
    public void save();
}

实现类:UserDaoImpl.java

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("Save running...");
    }
}

2.1.3 创建Spring核心配置文件
在类路径下(resources)创建applicationContext.xml配置文件;applicationContext该命名为任意取,一般取applicationContext


<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">
beans>

2.1.4 在Spring配置文件中配置UserDaoImpl


<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.learn.dao.impl.UserDaoImpl">bean>
beans>

2.1.5 使用Spring的API获得Bean实例

public class UserDaoDemo {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) app.getBean("userDao");
        userDao.save();
    }
}

3. Spring配置文件

3.1 bean标签的基本配置

用于配置对象交由Spring 来创建。默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。

3.2 bean标签范围配置

scope:指对象的作用范围,取值如下:

取值范围 说明
singleton 默认值,单例的
prototype 多例的
request WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
session WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
global session WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session

1)当scope的取值为singleton
Bean的实例化个数:1个
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
Bean的生命周期:

  • 对象创建:当应用加载,创建容器时,对象就被创建了
  • 对象运行:只要容器在,对象一直活着
  • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了

spring配置文件:

<bean id="userDao" class="com.learn.dao.impl.UserDaoImpl" scope="singleton"></bean>

测试代码:

    @Test
    public void SingletonUnitTest() {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao1 = (UserDao) app.getBean("userDao");
        UserDao userDao2 = (UserDao) app.getBean("userDao");
        System.out.println(userDao1);
        System.out.println(userDao2);
    }

在这里插入图片描述
2)当scope的取值为prototype
Bean的实例化个数:多个
Bean的实例化时机:当调用getBean()方法时实例化Bean

  • 对象创建:当使用对象时,创建新的对象实例
  • 对象运行:只要对象在使用中,就一直活着
  • 对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了

spring配置文件

<bean id="userDao" class="com.learn.dao.impl.UserDaoImpl" scope="prototype"></bean>

测试代码:同singleton
在这里插入图片描述

3.3 bean生命周期配置

init-method:指定类中的初始化方法名称(先执行无参构造方法【即是bean对象创建之后】,在执行该方法)
destroy-method:指定类中销毁方法名(在spring容器关闭的时候,只对单例有效)

spring 配置文件:

<bean id="userDao" class="com.learn.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>

UserDaoImpl.java 新增init()destroy()方法

    public void init() {
        System.out.println("初始化方法......");
    }

    public void destroy() {
        System.out.println("销毁方法......");
    }

测试代码:

    public void test2() {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao1 = (UserDao) app.getBean("userDao");
        System.out.println(userDao1);
        app.close();
    }

3.4 bean实例化三种方式

  • 无参构造方法实例化
  • 工厂静态方法实例化
  • 工厂实例方法实例化

1) 使用无参构造方法实例化
它会根据默认无参构造方法来创建类对象,如果bean中没有默认无参构造函数,将会创建失败

<bean id="userDao" class="com.learn.dao.impl.UserDaoImpl"></bean>

2)工厂静态方法实例化
工厂的静态方法返回Bean实例

public class StaticFactory {
    public static UserDao getUserDao() {
        return new UserDaoImpl();
    }
}

spring 配置文件

<bean id="userDao" class="com.learn.factory.StaticFactory" factory-method="getUserDao"></bean>

3) 工厂实例方法实例化
DynamicFactory类中添加获取UserDao对象的方法

public class DynamicFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

applicationContext.xml配置文件中的配置:

	
	<bean id="factory" class="com.learn.factory.DynamicFactory"/>
	
	<bean id="userDao" factory-bean="factory" factory-method="getUserDao"/>

测试代码:

    @Test
    public void test4() {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao1 = (UserDao) app.getBean("userDao");
        System.out.println(userDao1);
    }

3.5 bean的依赖注入入门

SSM笔记(1)Spring——IoC和DI_第4张图片
1、UserDaoImpl.java

//接口 UserDao.java
public interface UserDao {
    public void save();
}
//实现类
public class UserDaoImpl implements UserDao {

    public UserDaoImpl() {
        System.out.println("UserDaoImpl创建.......");
    }
    @Override
    public void save() {
        System.out.println("UserDao Save running...");
    }
}

2、UserServiceImpl.java

//接口 UserService.java
public interface UserService {
    public void save();
}
//实现类
public class UserServiceImpl implements UserService {
    @Override
    public void save() {
    	System.out.println("UserServiceImpl running...");
        //传统写法
        //UserDao userDao1 = new UserDaoImpl();
        //userDao1.save();

        //Spring 写法
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) app.getBean("userDao");
        userDao.save();
    }
}

3、测试类 controller UserController.java

public class UserController {
    public static void main(String[] args) {
        //传统写法
        //UserService userService1 = new UserServiceImpl();
        //userService1.save();

        //Spring 写法
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService)app.getBean("userService");
        userService.save();
    }
}

问题分析:
目前UserService实例和UserDao实例都存在与Spring容器中,当前的做法是在容器外部获得UserService实例和UserDao实例,然后在程序中进行结合。
SSM笔记(1)Spring——IoC和DI_第5张图片
因为UserServiceUserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部。
SSM笔记(1)Spring——IoC和DI_第6张图片
依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。

在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。

那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

3.6 bean的依赖注入方式

怎么将UserDao怎样注入到UserService内部呢?

  • set方法
  • 构造方法

1)set方法注入
UserServiceImpl中添加setUserDao方法

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    //快捷键:Alt+Insert
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

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

配置Spring容器调用set方法进行注入

    

    <bean id="userDao" class="com.learn.dao.impl.UserDaoImpl">bean>

    <bean id="userService" class="com.learn.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao">property>
    bean>

SSM笔记(1)Spring——IoC和DI_第7张图片
1)set方法注入—— P命名空间
P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:
首先,需要引入P命名空间:

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


<bean id="userDao1" class="com.learn.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.learn.service.impl.UserServiceImpl" p:userDao-ref="userDao1"/>

2)构造方法注入 —— 创建有参构造

public class UserServiceImpl implements UserService {
    private UserDao userDao;
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

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

配置Spring容器调用有参构造时进行注入

<bean id="userDao1" class="com.learn.dao.impl.UserDaoImpl"/>

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

3.7 bean的依赖注入的数据类型

上面的操作,都是注入的引用Bean,除了对象的引用可以注入外,普通数据类型、集合等都可以在容器中进行注入。
注入数据的三种数据类型

  • 普通数据类型
  • 引用数据类型
  • 集合数据类型

之前的操作都是对UserDao对象的引用进行注入的,下面将以set方法注入为
例,演示普通数据类型和集合数据类型的注入

1) 普通数据类型的注入

修改 UserDaoImpl.java

public class UserDaoImpl implements UserDao {

    private String username;
    private int age;

    public void setUsername(String username) {
        this.username = username;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public void save() {
        System.out.println(username + "==========" + age);
        System.out.println("UserDao Save running...");
    }

配置Spring容器

 <bean id="userDao" class="com.learn.dao.impl.UserDaoImpl">
     <property name="username" value="HaHa"/>
     <property name="age" value="18"/>
 bean>

2) 集合数据类型的注入

a、List属性的赋值

public class UserDaoImpl implements UserDao {
    private List<String> strList;
    /* 省略get/set */
    
	public void save() {
	      System.out.println(strList);
	}
}

配置Spring容器

<bean id="userDao1" class="com.learn.dao.impl.UserDaoImpl">
    <property name="strList">
        <list>
            <value>aaavalue>
            <value>bbbvalue>
            <value>cccvalue>
        list>
    property>
bean>

b、Mapproperties属性的赋值

新增User.java

public class User {

    private String name;
    private String addr;
	/* 省略get/set */
	
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", addr='" + addr + '\'' +
                '}';
    }
}

UserDaoImpl .java

public class UserDaoImpl implements UserDao {
    private Map<String, User> userMap;
    private Properties properties;
    /* 省略get/set */
    
	public void save() {
	      System.out.println(userMap);
	      System.out.println(properties);
	}
}

配置Spring容器

<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">
		
        <property name="userMap">
            <map>
                <entry key="u1" value-ref="user1">entry>
                <entry key="u2" value-ref="user2">entry>
            map>
        property>
        
        <property name="properties">
            <props>
                <prop key="p1">ppp1prop>
                <prop key="p2">ppp2prop>
                <prop key="p3">ppp3prop>
            props>
        property>
    bean>
	
    <bean id="user1" class="com.itheima.domain.User">
        <property name="name" value="tom"/>
        <property name="addr" value="beijing"/>
    bean>
    <bean id="user2" class="com.itheima.domain.User">
        <property name="name" value="lucy"/>
        <property name="addr" value="tianjin"/>
    bean>

3.8 引入其他配置文件(分模块开发)

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

在applicationContext.xml中的配置

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

4. Spring相关API

4.1 ApplicationContext的实现类

applicationContext:接口类型,代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象

1)ClassPathXmlApplicationContext
它是从类的根路径下加载配置文件 推荐使用这种

2)FileSystemXmlApplicationContext
它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

3)AnnotationConfigApplicationContext
当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

4.2 getBean()方法使用

//列如:UserService userService = (UserService) app.getBean("userService");
public Object getBean(String name) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(name);
}

//例如:UserService userService = app.getBean(UserService.class);
public <T> T getBean(Class<T> requiredType) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(requiredType);
}

其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。
当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错

你可能感兴趣的:(SSM框架学习,spring,java,后端)