zoukankan      html  css  js  c++  java
  • Spring Ioc基本理论

    Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

    Ioc核心理论回顾

    在Java中一个对象怎样才可以调用另外一个对象呢,一般会有以下几种方法。

    类别 描述 时间点
    外部传入 构造方法传入 创建引用对象时
    属性设置传入 设置对象状态时
    运行时做为参数传入 调用时
    内部创建 属性中直接创建 创建引用对象时
    初始化方法创建 创建引用对象时
    运行时动态创建 调用时

    上表可以看到, 引用一个对象可以在不同地点(其它引用者)、不同时间由不同的方法完成。如果B只是一个非常简单的对象 如直接new B(),怎样都不会觉得复杂,比如你从来不会觉得创建一个String 是一个件复杂的事情。但如果B 是一个有着复杂依赖的Service对象,这时在不同时机引用B将会变得很复杂。

    无时无刻都要维护B的复杂依赖关系,试想B对象如果项目中有上百过,系统复杂度将会成陪数增加。

    IOC容器 的出现正是为解决这一问题,其可以将对象的构建方式统一,并且自动维护对象的依赖关系,从而降低系统的实现成本。前提是需要提前对目标对象基于XML进行声明。

    实体Bean的创建

    Version:0.9 StartHTML:0000000105 EndHTML:0000000765 StartFragment:0000000141 EndFragment:0000000725

    • 基于Class构建
    • 构造方法构建
    • 静态工厂方法创建
    • FactoryBean创建

    1、基于ClassName构建

    <bean class="com.tuling.spring.HelloSpring"></bean>
    

    这是最常规的⽅法,其原理是在spring底层会基于class 属性 通过反射进⾏构建。

    2、构造方法构建

    <bean class="com.tuling.spring.HelloSpring">
        <constructor-arg name="name" type="java.lang.String" value="luban"/>
        <constructor-arg index="1" type="java.lang.String" value="sex" />
    </bean>
    

    如果需要基于参数进行构建,就采用构造方法构建,其对应属性如下:
    name:构造方法参数变量名称
    type:参数类型
    index:参数索引,从0开始
    value:参数值,spring 会自动转换成参数实际类型值
    ref:引用容串的其它对象

    3、静态工厂方法创建

    <bean class="com.tuling.spring.HelloSpring" factory-method="build">
        <constructor-arg name="type" type="java.lang.String" value="B"/>
    </bean>
    

    如果你正在对一个对象进行A/B测试 ,就可以采用静态工厂方法的方式创建,其于策略创建不同的对像或填充不同的属性。
    该模式下必须创建一个静态工厂方法,并且方法返回该实例,spring 会调用该静态方法创建对象。

    public static HelloSpring build(String type) {
        if (type.equals("A")) {
            return new HelloSpring("luban", "man");
        } else if (type.equals("B")) {
            return new HelloSpring("diaocan", "woman");
        } else {
            throw new IllegalArgumentException("type must A or B");
        }
    }
    

    4、FactoryBean创建

    <bean class="com.tuling.spring.LubanFactoryBean" id="helloSpring123"></bean>
    

    指定一个Bean工厂来创建对象,对象构建初始化 完全交给该工厂来实现。配置Bean时指定该工厂类的类名。

    public class LubanFactoryBean implements FactoryBean {
        @Override
        public Object getObject() throws Exception {
            return new HelloSpring();
        }
        @Override
        public Class<?> getObjectType() {
            return HelloSpring.class;
        }
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    

    bean的基本特性

    • 作用范围
    • 生命周期
    • 装载机制

    1、作用范围

    很多时候Bean对象是无状态的 ,而有些又是有状态的 无状态的对象我们采用单例即可,而有状态则必须是多例的模式,通过scope 即可创建
    scope=“prototype”
    scope=“singleton”

    scope=“prototype
    <bean class="com.tuling.spring.HelloSpring" scope="prototype">
    </bean>
    

    如果一个Bean设置成 prototype 我们可以 通过BeanFactoryAware 获取 BeanFactory 对象即可每次获取的都是新对像。

    2、生命周期

    Bean对象的创建、初始化、销毁即是Bean的生命周期。通过 init-method、destroy-method 属性可以分别指定期构建方法与初始方法。

    <bean class="com.tuling.spring.HelloSpring" init-method="init" destroy-method="destroy"></bean>
    

    如果觉得麻烦,可以让Bean去实现 InitializingBean.afterPropertiesSet()、DisposableBean.destroy()方法。分别对应 初始和销毁方法

    3、加载机制

    指示Bean在何时进行加载。设置lazy-init 即可,其值如下:
    true: 懒加载,即延迟加载
    false:非懒加载,容器启动时即创建对象
    default:默认,采用default-lazy-init 中指定值,如果default-lazy-init 没指定就是false

    <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"
    default-lazy-init="true">
    

    什么时候使用懒加载?
    懒加载会容器启动的更快,而非懒加载可以容器启动时更快的发现程序当中的错误 ,选择哪一个就看追求的是启动速度,还是希望更早的发现错误,一般我们会选 择后者。

    依赖注入

    试想IOC中如果没有依赖注入,那这个框架就只能帮助我们构建一些简单的Bean,而之前所说的复杂Bean的构建问题将无法解决,spring这个框架不可能会像现在这样成功。 spring 中 ioc 如何依赖注入呢。有以下几种方式:

    1. set方法注入
    2. 构造方法注入
    3. 自动注入(byName、byType)
    4. 方法注入(lookup-method)

    1、set方法注入

    <bean class="com.tuling.spring.HelloSpring">
        <property name="fine" ref="fineSpring"/>
    </bean>
    

    2、构造方法注入

    <bean class="com.tuling.spring.HelloSpring">
        <constructor-arg name="fine">
            <bean class="com.tuling.spring.FineSpring"/>
        </constructor-arg>
    </bean>
    

    3、自动注入(byNameyTypeconstructor)

    <bean id="helloSpringAutowireConstructor" class="com.tuling.spring.HelloSpring" autowire="byName">
    </bean>
    

    byName:基于变量名与bean 名称相同作为依据插入
    byType:基于变量类别与bean 名称作
    constructor:基于IOC中bean 与构造方法进行匹配(语义模糊,不推荐)

    4、依赖方法注入(lookup-method)

    当一个单例的Bean,依赖于一个多例的Bean,用常规方法只会被注入一次,如果每次都想要获取一个全新实例就可以采用lookup-method 方法来实现。

    #编写一个抽像类
    public abstract class MethodInject {
        public void handlerRequest() {
          // 通过对该抽像方法的调用获取最新实例
            getFine();
        }
        # 编写一个抽像方法
        public abstract FineSpring getFine();
    }
    // 设定抽像方法实现
    <bean id="MethodInject" class="com.tuling.spring.MethodInject">
        <lookup-method name="getFine" bean="fine"></lookup-method>
    </bean>
    

    该操作的原理是基于动态代理技术,重新生成一个继承至目标类,然后重写抽像方法到达注入目的。前面说所单例Bean依赖多例Bean这种情况也可以通过实现 ApplicationContextAware 、BeanFactoryAware 接口来获取BeanFactory 实例,从而可以直接调用getBean方法获取新实例,推荐使用该方法,相比lookup-method语义逻辑更清楚一些。

    |类别|描述|时间点|
    |外部传入 | 构造方法传入 |创建引用对象时|
    | | 属性设置传入 | 设置对象状态时 |
    | | 运行时做为参数传入 | 调用时 |
    | 内部创建 | 属性中直接创建 | 创建引用对象时 |
    | | 初始化方法创建 | 创建引用对象时 |
    | | 运行时动态创建 | 调用时 |

    类别 描述 时间点
    外部传入 构造方法传入
  • 相关阅读:
    CF516D Drazil and Morning Exercise
    Daily question
    Promise练习
    window.location
    微信二次分享描述变链接,标题也没显示设置的标题,图片也不显示
    Vue项目配置微信分享
    swiper 轮播图圆角滑动变会变成直角然后再回到圆角(iOS)
    IOS下图片不能显示问题的解决办法
    alert组件关闭跳转页面,页面无法滚动(Vue)
    C# .net framework .net core 3.1 请求参数校验, DataAnnotations, 自定义参数校验
  • 原文地址:https://www.cnblogs.com/bangaj/p/14853503.html
Copyright © 2011-2022 走看看