Spring IOC之初体验

本文仅限于记录自己学习java路上对于 IOC 的理解,主要是自己根据他人文献的总结和学习,文中也没啥有深度的东西,大牛和大佬可以忽略本文,以免浪费您宝贵的时间

1 原生开发的问题

  1. 传统Web开发存在硬编码所造成的过度程序耦合(例如:Service中作为属性Dao对象)。

  1. 部分Java EE API较为复杂,使用效率低(例如:JDBC开发步骤)。

  1. 侵入性强,移植性差(例如:DAO实现的更换,从Connection到SqlSession)。

2 Spring概述

  • Spring是一个项目管理框架,同时也是一套Java EE解决方案。

  • Spring是众多优秀设计模式的组合(工厂、单例、代理、适配器、包装器、观察者、模板、策略)。

  • Spring并未替代现有框架产品,而是将众多框架进行有机整合,简化企业级开发,俗称"胶水框架"。

官方网站:https://spring.io/

3 Spring架构组成

4 Spring IOC

4.1 什么是IOC?

  1. IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”。

控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。

  1. IOC也叫 依赖注入

“哪些方面的控制被反转了呢?”,Martin Fowler经过详细地分析和论证后

他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。

其实依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中

  1. 底层

XML解析、工厂设计模式反射

4.2 IOC 的主要作用是什么?

1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IOC 这个概念。借助于“第三方”实现具有依赖关系的对象之间的解耦.

反转了依赖关系的满足方式,由之前的自己创建依赖对象,变为由工厂推送。(变主动为被动,即反转)

解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健.

扩充话题: 解耦

解耦通俗地说就是两个东西原来互相影响,现在让他们独立发展,每个地方都只做一件事情,只要一个地方负责了多项事情,就存在解耦的可能。

简单通俗的理解就是,现实生活中的很多方面都要解耦,比如usb接口使硬件解耦了,java虚拟机使软件与具体操作系统解耦了,tcp/ip协议使使用网络与具体的硬件网络解耦了

解耦带来的好处是:①提高问题的解决概率;②提高问题的解决效果;③提高问题的解决速度;④降低将来爆发隐患的可能性。

4.3 IOC初体验

@Data
public class User {
    private Integer id;
    private String username;
    private String password;

    private  Car car;
}

applicationContext.xml中的< beans >内部配置bean标签

 <!-- bean创建对象并赋值
      该id属性是标识单个 bean 定义的字符串。(不能重复)
      该class属性定义 bean 的类型并使用完全限定的类名。
  -->
    <bean id="OneCar" class="com.pojo.Car">
        <property name="cid"  value="1"></property>
        <property name="cname"  value="五菱"></property>
    </bean>
    <bean id="user" class="com.pojo.User">
        <property name="id" value="1"></property>
        <property name="username" value="张三"></property>
        <property name="password" value="123123"></property>
        <property name="car" ref="OneCar"></property>
    </bean>

4.4测试

  //加载配置文件
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        //创建Bean
         User user =(User)applicationContext.getBean("user");
        //输出
        System.out.println(user);

4.5 复杂类型的注入/集合类型的注入

1、用于给数组结构注入的标签:array

2、用于给List结构集合注入的标签:list set

3、用于个Map结构集合注入的标签:map properties

//实体类
@Data
public class CollectionVo {
    private String [] arr;
    private List list;
    private Set set;
    private Map map;
    private Properties properties;
}
    <bean id="sb" class="com.pojo.CollectionVo">
        <property name="arr">
<!--    数组        -->
            <array>
                <value>亢龙有悔</value>
                <value>潜龙勿用</value>
                <value>见龙在田</value>
            </array>
        </property>
<!--        list集合-->
        <property name="list">
            <list>
                <value>战龙在野</value>
                <value>泽里龙吟</value>
                <value>泽里龙吟</value>
                <ref bean="user"></ref>
            </list>
        </property>
<!--        set集合-->
        <property name="set">
            <set>
                <value>神龙摆尾</value>
                <value>龙跃在渊</value>
                <value>龙涉大川</value>
                <ref bean="user"></ref>
            </set>
        </property>
<!--        map集合-->
        <property name="map">
            <map>
               <entry key="1" value="龙啸万里"></entry>
               <entry key="2" value="群龙无首"></entry>
                <entry key-ref="user" value-ref="OneCar"></entry>
            </map>
        </property>
        <!-- properties -->
        <property name="properties">
            <props>
                <prop key="username">root</prop>
                <prop key="password">666666</prop>
                <prop key="url">jdbc:mysql:///db_name</prop>
                <prop key="driverClassName">com.mysql.cj.jdbc.Driver</prop>
            </props>
        </property>
    </bean>

构造注入

@Data
public class User {
    private Integer id;
    private String username;
    private String password;

    private  Car car;
    
    public User(Integer id, String username, String password, Car car) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.car = car;
        System.out.println("第一个构造器");
    }
        //这里特意给id属性位置
    public User(String username, String password, Car car, Integer id ) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.car = car;
        System.out.println("第二个构造器");
    }
}
  <!--
使用的标签:constructor-arg
标签出现的位置:bean标签的内部

标签中的属性:
​           name:用于指定给构造函数中指定名称的参数赋值                                     
​           value:用于提供基本类型和String类型的数据
​           ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
​           type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
​           index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始 
       -->
        <bean id="car" class="com.pojo.Car">
            <property name="cid"  value="1"></property>
            <property name="cname"  value="白眉大虾"></property>
        </bean>
    <bean id="user" class="com.pojo.User">
        <constructor-arg name="id" value="1" index="3"></constructor-arg>
        <constructor-arg name="username" value="白毛猫王" index="0"></constructor-arg>
        <constructor-arg name="password" value="6666" index="1"></constructor-arg>
        <constructor-arg name="car" ref="car" index="2"></constructor-arg>
    </bean>

5 Spring对bean的管理细节

  • 注意:需要根据场景决定对象的单例(IOC中实例唯一)、多例模式(调用就是创建新对象)。

  • 可以共用:Service、DAO、SqlSessionFactory(或者是所有的工厂)。

  • 不可共用:Connection、SqlSession、ShoppingCart。

<!--
    singleton(默认):每次调用工厂,得到的都是同一个对象。
    prototype:每次调用工厂,都会创建新的对象。
-->
<bean id="mc" class="com.basic.MyClass" scope="singleton" />

6 bean对象的生命周期

生命周期属性:配置一个方法作为生命周期初始化方法. spring会在对象创建之后立即调用: init-method配置一个方法作为生命周期的销毁方法. spring容器在关闭并销毁所有容器中的对象之前调用: destory-method

<!--
  该id属性是标识单个 bean 定义的字符串。(不能重复)
  该class属性定义 bean 的类型并使用完全限定的类名。
  scope:常用的是单例(singleton)和多例(prototype)
  init-method:创建对象后执行的初始化方法
  destroy-method:对象销毁后执行(如果是多例模式下不执行)
-->
<bean id = "user" class = "com.pojo.User"
      scope="singleton" init-method="initUser" destroy-method="destroyUser">
</bean>
/**
 * User实体类
 */
public class User {

    private Integer id;
    private String name;
    private String password;

    public User() {
        System.out.println("无参构造");
    }

    /**
     * 初始化方法,创建对象后执行
     */
    public void initUser() {
        System.out.println("User 初始化方法");
    }

    /**
     * 销毁方法,销毁spring容器中对象后执行
     */
    public void destroyUser() {
        System.out.println("User 销毁方法");
    }

}
/**
 * 测试生命周期相关方法
 */
@Test
public void testLife() {
    //创建ClassPathXmlApplicationContext对象
    ClassPathXmlApplicationContext applicationContext
        = new ClassPathXmlApplicationContext("applicationContext.xml");

    //获取对象
    User user = (User) applicationContext.getBean("user");

    System.out.println(user);

    //关闭
    applicationContext.close();
}

7 IOC带来的好处

IOC核心思想 在于

第一,资源集中管理,实现资源的可配置和易管理

第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值