柏竹 柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档

柏竹

奋斗柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档
  • Java基础

  • JavaWeb

  • 拓展技术

  • 框架技术

  • 数据库

  • 数据结构

  • Spring

    • Spring
    • Spring IOC
      • 对象说明和获取
        • BeanFactory
        • ApplicationContext
      • Bean
        • 应用示例
        • Bean 作用域
      • 依赖注入 DI
        • 属性注入
        • 自动注入
        • byName装配
        • byType
      • 注解装配Bean
        • 包扫描
        • 自动注入
    • Spring AOP
    • Spring拓展
  • SpringMVC

  • SpringBoot

  • SpringClound

  • Ruoyi-Vue-Plus

  • 后端
  • Spring
柏竹
2021-06-25
目录

Spring IOC

# Spring IOC

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想

Ioc 在开发中,无需自行实例对象,而是有 Spring Ioc容器 创建。Spring容器会负责控制程序之间的关系,而不是由代码直接控制,因此,控制权由 Spring容器 接管,控制权发生了反转,是Ioc设计思想

Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext

# 对象说明和获取

# BeanFactory

BeanFactory接口 是一个管理Bean的工厂, 也是最顶层的接口 , 定义了Ioc容器的基本功能规范 . 它主要根据xml配置文件中的定义Bean进行管理,主要负责初始化各种Bean对象

可进行 延迟加载 , 他们会在调用的时候进行加载对象

// 加载 xml文件
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("application.xml"));
beanFactory.getBean("...");

BeanFactory有以下三个重要子接口 :

  • ListableBeanFactory接口 : Bean可序列化
  • HierarchicalBeanFactory接口 : Bean有继承关系 , 每个Bean有父Bean
  • AutowireCapableBeanFactory接口 : Bean的自动装配规则

# ApplicationContext

ApplicationContext 是 BeanFactory 的子接口,也是 应用上下文。支持了 BeanFactory 的所有功能

ApplicationContext接口有两个常用的 实现类,主要用于加载配置文件的

  • ClassPathXmlApplicationContext 通过 类路径上下文加载

    ==new ClassPathXmlApplicationContext(<Spring配置文件的名>)==

    将普通路径解释为包含包路径的类路径资源名称(例如“mypackage/myresource.txt”)

  • FileSystemXmlApplicationContext 通过 文件系统路径/URL 加载指定配置文件

    ==new FileSystemXmlApplicationContext(<文件系统路径/URL>);==

    **注意:**普通路径将始终被解释为相对于当前 VM 工作目录,即使它们以斜杠开头 使用显式的“file:”前缀来强制使用绝对文件路径

对象获取实例

//指定决定绝对路径的文件
new FileSystemXmlApplicationContext(new FileSystemResource("D:\applicationContext.xml"));

//指定相对根路径的文件
new ClassPathXmlApplicationContext("applicationContext.xml");

# Bean

Spring Bean标签 可以想象成 我们使用的 实例对象 ,Spring是通过在配置文件中进行调取出来的实例对象(反射原理) . 在以往的操作 是通过 硬编码 new 出来的新对象 ,因此 我们需要提前 编写好配置文件

Bean标签,因此我们需要自己手动配置Bean对象,以下有两种Spring配置文件支持的格式

  • Properties配置文件 (只能存在键值形式存在
  • XML配置文件

XML配置文件

该配置文件的根元素是 <beans>,该元素包含了多个 <bean> 子元素,每一个 <bean> 子元素定义了一个对象

<!-- 使用id属性定义person1,其对应的实现类为com.mengma.person1 (类路径及包路径)-->
<bean id="person1" class="com.mengma.person1 " />
<!--使用name属性定义person2,其对应的实现类为com.mengma.domain.Person2 (类路径及包路径) -->
<bean name="Person2" class="com.mengma.domain.Person2"/>

bean标签属性说明

属性 值 说明
id String Bean 的唯一标识符,Spring IoC 容器对 Bean的 配置和管理都通过该属性完成
name String Bean 的名称,可通过 name属性 为同一个 Bean同时指定多个名称,每个名之间用 逗号/分号 隔开。Spring容器 可通过 name属性 配置和管理容器中的 Bean
class String Bean 的具体实现类 (全限定名
scope String 定义 的 [Bean作用域](#Bean 作用域) (点击跳转
autowire byName | byType Bean自动装配,根据定义的 name/type 进行自动装配
lazy-init boolean 延迟加载 (默认false),在getBean()方法调用时才实例
init-method String 初始化对象方法
destroy-method String 销毁对象方法

# 应用示例

实体类 People.calss

类型 成员变量
String name
String age

配置文件 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实例方式
        - 构造器实例
        - 静态工厂实例
        - 实例工厂实例
     -->
    <!-- 无参构造器 -->
    <bean id="person1" class="com.sans.Person"/>
    <!-- 有参构造器 -->
    <!-- Bean属性 初始化/销毁 -->
    <bean id="person2" class="com.sans.Person" init-method="init" destroy-method="destroy">
        <constructor-arg index="0" value="张三"/>
        <constructor-arg index="1" value="Spring挺简单的嘛"/>
    </bean>

    <!-- 静态工厂实例 -->
    <bean id="personFactory1" class="com.sans.MyFactory" factory-method="instanceLisi" />

    <!-- 实例工厂实例 -->
    <bean id="factory" class="com.sans.MyFactory"/>
    <bean id="personFactory2" factory-bean="factory" factory-method="instanceZhangsan"/>
</beans>

测试

@Test
public void beanExampleTest() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person person1 = (Person) applicationContext.getBean("person1");
    Person person2 = (Person) applicationContext.getBean("person2");
    Person factory1 = (Person) applicationContext.getBean("personFactory1");
    Person factory2 = (Person) applicationContext.getBean("personFactory2");

    System.out.println("person1 = " + person1);
    System.out.println("person2 = " + person2);
    System.out.println("factory1 = " + factory1);
    System.out.println("factory2 = " + factory2);

    /* 结果:
        Person对象初始化: Person{name='张三', msg='Spring挺简单的嘛'}
        Person对象初始化: Person{name='null', msg='null'}
        person1 = Person{name='null', msg='null'}
        person2 = Person{name='张三', msg='Spring挺简单的嘛'}
        factory1 = Person{name='李四', msg='我也这么觉得!'}
        factory2 = Person{name='张三', msg='Spring挺简单的嘛'}
     */
}

# Bean 作用域

Spring Bean作用域,可方便的管理 Bean应用的时期 以及场景

只需在 <bean>.scope属性 配置范围值即可。scope范围值有以下6种:

属性值 说明
singleton 单例模式,每次在容器获取都是同一 Bean实例 (默认值)
prototype 原型模式,每次在容器获取都是新的 Bean实例
request 每次request请求,容器都会创建一个 Bean实例。该域只在当前 request 内有效
session 每次session会话,不同的会话使用的 Bean实例不同。该域仅在当前 Session 内有效
application Web应用 共享一个 Bean实例。该域在当前 ServletContext 内有效(和单例模式差不多
websocket websocket 的作用域是 WebSocket ,即在整个 WebSocket 中有效

# 依赖注入 DI

DI—Dependency Injection,即 依赖注入。需要通过 简单的配置,而无需任何代码就可指定目标需要的资源。而注入的方式有:

  • setter
  • 构造器
  • 接口
  • 注解

Ioc 和 DI 是同一个概念的不同角度描述。IoC是一种思想;DI是实现它的手段 Spring框架使用依 赖注入实现IoC

# 属性注入

Bean 属性注入,是将属性数据注入到 Bean 中的过程

实现属性注入方式 :

  • 构造函数注入
  • setter 注入

bean标签 代表的是一个实例对象,实例对象中 包含多个 属性/子标签 等。以下说明当中的标签以及作用

constructor-arg标签 构造实例。应用的构造器指定的参数进行实例对象。该标签有以下属性

属性 值 说明
index String 传参的序号(从0开始
value String 指定传递的 常量值
name String 构造方法对应的 形参名称
ref String 引用配置 Bean实例
type String 传参的属性类型

**ref:**引用可通过 id/name 属性的值 进行引入

property标签 set注入。该标签是通过 属性的set方法进行填充数据,因此属性一定要有set方法。该标签有以下属性

属性 值 说明
name String 属性名称
ref String 引用配置 Bean实例
value String 配置指定 常量值

注意:

  • name属性 在配置的时候,如果失去高亮,那么很有可能实体类没有配置该属性的 set方法 (前提:需要配置Spring上下文

  • set注入P命名空间,使用前提父标签需要引入以下配置

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

集合属性配置 在配置当中难免会存在一些特殊情况,例如集合属性的配置。以下是 集合标签的说明

标签 说明
<array> 封装数组(可重复
<list> 封装 List (可重复
<set> 封装 Set(不可重复
<map> 封装 Map (k和v均可任意类型
<props> 封装 Map (k和v都是字符串类型
  • <array> 封装数组(可重复

    • <ref>.bean:引用对象元素
    • <value>:常量值
  • <list> 封装List(可重复

    • <ref>.bean:引用对象元素
    • <value>:常量值
  • <set> 封装 Set(不可重复

    • <ref>.bean:引用对象元素
    • <value>:常量值
  • <map> 封装 Map (k和v均可任意类型

    • <entry>.key:Map键 K

    • <entry>.value:Map值 V

      键和值可以 都可以 引用实例对象。引用方式 属性名后缀添加 -ref

  • <props> 封装 Map (k和v都是字符串类型

    • <prop>.key:Map键 K
    • <prop>:Map值 V(标签包裹

应用示例

步骤:

  1. 编写好实体类的属性以及get/set方法
  2. 在 xml/Properties 配置上编辑 bean实例
  3. 通过 ==new ClassPathXmlApplicationContext(<配置文件路径>).getBean()==方法获取实例对象

实体类 Person.class

public class Person {
    private String name;
    private String msg;

    // 数组类型
    private Person[] array;

    // 集合 特殊应用
    private List<Person> list;
    private Set<String> set;
    private Map<String, Object> map;
    private Properties properties;

    // 构造方法注入
    public Person() {
    }
    
    public Person(String name, String msg) {
        this.name = name;
        this.msg = msg;
    }

    // 省略 自动生成的 get/set 方法

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", msg='" + msg + '\'' +
                '}';
    }
}

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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 无参构造 -->
    <bean id="person1" class="com.sans.bean.Person"/>
    <!-- 全参构造 -->
    <bean id="person2" class="com.sans.bean.Person">
        <constructor-arg index="0" value="张三"/>
        <constructor-arg index="1" value="Spring挺简单的嘛"/>
    </bean>

    <!-- set注入 -->
    <bean id="person3" class="com.sans.bean.Person">
        <property name="name" value="李四"/>
        <property name="msg" value="我也觉得"/>
    </bean>
    <!-- P命名空间 set注入-->
    <bean id="person4" class="com.sans.bean.Person" p:name="王五" p:msg="还行吧!挺好的"/>
    <!-- set方法 集合注入 -->
    <bean id="person5" class="com.sans.bean.Person">

        <!-- 数组类型 -->
        <property name="array">
            <array>
                <ref bean="person1"/>
                <ref bean="person2"/>
                <ref bean="person3"/>
                <ref bean="person4"/>
            </array>
        </property>
        
        <!-- List类型 -->
        <property name="list">
            <list>
                <ref bean="person1"/>
                <ref bean="person2"/>
                <ref bean="person3"/>
                <ref bean="person4"/>
            </list>
        </property>
        
        <!-- Set类型 -->
        <property name="set">
            <set>
                <value>张三</value>
                <value>李四</value>
                <value>王五</value>
            </set>
        </property>

        <!-- Map类型 -->
        <property name="map">
            <map>
                <entry key="No1" value="张三" />
                <entry key="No2" value="李四"/>
                <entry key="No3" value="王五"/>
            </map>
        </property>

        <property name="properties">
            <props>
                <prop key="No1">张三</prop>
                <prop key="No2">李四</prop>
                <prop key="No3">王五</prop>
                <prop key="No4">12</prop>
            </props>
        </property>
    </bean>
</beans>

测试结果

public class Demo {

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

    /* 通过构造器 实例 */
    @Test
    public void constructor() {
        Person person1 = (Person) applicationContext.getBean("person1");
        Person person2 = (Person) applicationContext.getBean("person2");
        System.out.println("person1 = " + person1);
        System.out.println("person2 = " + person2);
        /* 结果 toString方法直接打印
            person1 = Person{name='null', msg='null'}
            person2 = Person{name='张三', msg='Spring挺简单的嘛'}
         */
    }

    /* set注入 实例 */
    @Test
    public void setInjection() {
        Person person3 = (Person) applicationContext.getBean("person3");
        Person person4 = (Person) applicationContext.getBean("person4");
        Person person5 = (Person) applicationContext.getBean("person5");
        System.out.println("person3 = " + person3);
        System.out.println("person4 = " + person4);

        // 由于 person4对象 针对了 数组/集合 类型的属性测试
        System.out.println("person5.getArray() = " + Arrays.toString(person5.getArray()));
        System.out.println("person5.getList() = ");
        person5.getList().forEach(person -> System.out.println("\t"+person));
        System.out.println("person5.getSet() = " + person5.getSet());
        System.out.println("person5.getMsg() = ");
        person5.getMap().forEach((key, value) -> System.out.println("\t"+key+" : "+value));
        System.out.println("person5.getProperties() = " + person5.getProperties());
        /* 结果 (PS: 由于有一个是无参的引用因此为null
            person3 = Person{name='李四', msg='我也觉得'}
            person4 = Person{name='王五', msg='还行吧!挺好的'}
            person5.getArray() = [Person{name='null', msg='null'}, Person{name='张三', msg='Spring挺简单的嘛'}, Person{name='李四', msg='我也觉得'}, Person{name='王五', msg='还行吧!挺好的'}]
            person5.getList() = 
            	Person{name='null', msg='null'}
            	Person{name='张三', msg='Spring挺简单的嘛'}
            	Person{name='李四', msg='我也觉得'}
            	Person{name='王五', msg='还行吧!挺好的'}
            person5.getSet() = [张三, 李四, 王五]
            person5.getMsg() = 
            	No1 : 张三
            	No2 : 李四
            	No3 : 王五
            person5.getProperties() = {No2=李四, No1=张三, No4=12, No3=王五}
         */

    }
}

# 自动注入

Spring 的自动注入功能可以让 Spring容器 依据指定规则,为指定的 Bean 从应用的上下文中查找它所依赖的 Bean 并自动建立 Bean 之间的依赖关系。而这一过程是在完全不使用任何 <constructor-arg>.ref/ <property>.ref 形式配置Bean

自动注入 主要作用是 简化 Spring 在 XML配置应用,因此在大工程中降低很多工作量

Spring容器 默认不支持自动装配的,需要在配置文件中的 <bean>.autowire属性应用

<bean>.autowire属性说明

属性值 说明
byName 根据 名称 自动注入 (id/name均可引用
byType 根据 类型 自动注入
constructor 根据 构造器参数 的数据类型,进行 byType模式 的自动装配
default 默认采用上一级元素 <beans>设置的自动装配规则(default-autowire)进行装配
no 默认值,不使用自动注入

# byName装配

ByName表示 按属性名称自动装配,配置文件中 <bean>.id/name属性值 必须与 类中属性名称 相同

示例

Person实体对象 (省略

实体工厂对象

public class MyFactory {
    private Person person1;
    private Person person2;
    // 省略 自动生成的 set/get 方法
}

配置文件

<!-- 使用 id/name 属性 标明  -->
<bean id="person1" class="com.sans.bean.Person" p:name="张三" p:msg="Spring挺简单的嘛!"/>
<bean name="person2" class="com.sans.bean.Person" p:name="李四" p:msg="我也觉得"/>

<!--  byName -->
<bean id="Myfactory" class="com.sans.MyFactory" autowire="byName"/>

测试

@Test
public void auotInjection() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    MyFactory factory = (MyFactory) applicationContext.getBean("Myfactory");

    System.out.println(factory.getPerson1());
    System.out.println(factory.getPerson2());
    /* 结果:
        Person{name='张三', msg='Spring挺简单的嘛!'}
        Person{name='李四', msg='我也觉得'}
    */
}

# byType

byType表示 按属性类型自动装配,配置文件中 被注入类中的属性类型 与 容器内的Bean类型 相同,则自动注入

注意:

  • 如果类中有一个以上的相同属性类型,那么该类型全部自动注入
  • 在Spring Ioc容器上下文应用中不能存在相同类型的 Bean实例,否则无法引用

示例

Person实体对象 (省略

实体工厂对象 (省略

配置文件

<bean id="person1" class="com.sans.bean.Person" p:name="张三" p:msg="Spring挺简单的嘛!"/>
<!--    不能存在相同类型
<bean name="person2" class="com.sans.bean.Person" p:name="李四" p:msg="我也觉得"/>-->

<!-- byClass -->
<bean id="Myfactory" class="com.sans.MyFactory" autowire="byType"/>

测试

@Test
public void auotInjection() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    MyFactory factory = (MyFactory) applicationContext.getBean("Myfactory");

    System.out.println(factory.getPerson1());
    System.out.println(factory.getPerson2());
    /* 结果:
        Person{name='张三', msg='Spring挺简单的嘛!'}
		Person{name='张三', msg='Spring挺简单的嘛!'}
    */
}

# 注解装配Bean

在 Spring 中,尽管使用 XML配置文件可实现 Bean 的装配工作,如果应用中 Bean 的数量较多,会导致 XML配置文件过于臃肿,从而给维护和升级带来一定的困难,因此 Spring 提供了注解应用,需要在原有的运行环境基础上做些变化,由此减少过多的Bean

@Component

在类上添加上 @Component注解 表示该类实例的对象的权限交给 Spring容器 。注解的value属性用于指定bean的 id值 或 name值 ,但一般情况可省略 value 属性!(该注解指定id是类名的首字母小写)

以下注解与 @Component注解 用法和功能 相同,表达的含义不同!

  • @Repository

    dao层实现类的注解(持久层)

  • @Service

    service层实现类的注解(业务层)

  • @Controller

    controller层实现类的注解(控制层)

PS : 应用前提需要扫描 , 点击跳转

@Value

该 注解 是为指定属性 注入值。该注解用在 类的属性 或 指定set方法上 。 其注解注入 原理 和 set方法 写入是一样,因此 set方法 也可

package com;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyUser {
    //方式1
    @Value("001")
    private int id;
    @Value("张三")
    private String name;
    @Value("23")
    private int age;
    @Value("洛杉矶")
    private String locateion;
    
    ···
    
    //方式2
    @Value("001")
    public void setId(int id) {
        this.id = id;
    }
    @Value("张三")
    public void setName(String name) {
        this.name = name;
    }
    @Value("23")
    public void setAge(int age) {
        this.age = age;
    }
    @Value("洛杉矶")
    public void setLocateion(String locateion) {
        this.locateion = locateion;
    }
    
   	···
}

# 包扫描

需要在 xml配置文件中配置组件扫描器,用于在指定包中扫描的注解。如果未添加扫描,则对象添加的注解 将无法实例化

xml配置文件 添加扫描

  1. beans标签 配置属性 xmlns:context属性: ==xmlns:context="http://www.springframework.org/schema/context"== xsi:schemaLocation属性(添加值): http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context.xsd

    ···
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
    	···
    </beans>
    
  2. context:component-scan标签 指定包扫描 分隔符可以使用逗号(,)分号(;)还可以使用空格,不建议使用空格。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!--    包扫描 方法1: (包路径 Annotation.dao、Annotation.service、Annotation.controller)-->
    	    <context:component-scan base-package="Annotation.dao"/>
    	    <context:component-scan base-package="Annotation.service"/>
    	    <context:component-scan base-package="Annotation.controller"/>
    <!--    包扫描 方法2: (包路径 Annotation.dao、Annotation.service、Annotation.controller)-->
    	    <context:component-scan base-package="Annotation.dao;Annotation.service;Annotation.dao"/>
    </beans>
    
  3. 添加对应注解即可

# 自动注入

自动注入指定对象的前提,需要为该对象添加注解,且 上级包 或 指定类 有扫描到!

@Autowired

用于对 Bean 的 属性变量、属性Set方法 及构造方法进行标注(构造方法应用的前提,参数必须指定的是对应的实例对象),配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean类型 进行装配

@Autowired 还有一个属性 required,默认值为 true,表示匹配失败后终止程序运行;若值为 false,则匹配失败后 其属性值为 null

@Autowired 不同范围的作用

范围 说明
构造器 构造器会被Spring调用以完成Bean的初始化
参数 参数会与Spring容器中的Bean匹配并传入
setter方法 setter方法会被Spring调用将相关Bean注入
成员变量 Spring会直接将相关Bean注入给字段

@Qualifier

与 @Autowired 注解配合使用,会将默认的按 Bean类型 装配修改为按 Bean实例队形名称 装配,Bean 的实例名称由 @Qualifier 注解的 value参数 指定

@Resource

该注解 在jdk1.6版本以上 支持使用,Bean属性可指定按照 类型(type) 或 名称(name) 进行自动注入,可在 属性变量、属性Set方法 进行使用

@Autowired 与 @Resource 区别

注解 说明
@Autowired 根据 对象类型 进行获取 Bean对象
@Resource 根据 方法名称 进行获取 Bean对象

提示

SpringBoot3.0.2以下版本 , @Resource注解 需要参数 name指定方法名称

#spring
上次更新: 2023/03/12, 00:43:49

← Spring Spring AOP→

最近更新
01
HTTPS自动续签
10-21
02
博客搭建-简化版(脚本)
10-20
03
ruoyi-vue-plus-部署篇
07-13
更多文章>
Theme by Vdoing | Copyright © 2019-2024 | 桂ICP备2022009417号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式