SSM——11.Spring IOC

这篇文章我们将主要来讨论一下spring的IOC

目录

1.IOC概述

2. IOC容器的底层原理

2.1 概述

2.2 上面的三种技术如何实现IOC?

2.3 IOC(接口)

3.Spring框架的Bean管理

3.1 什么是bean管理

3.2 bean管理操作的两种方式

3.3 基于xml配置文件的方式实现bean管理

3.3.1 基于xml方式创建对象

3.3.2 基于xml方式注入属性

3.4 基于注解的方式实现bean管理

3.4.1 注解概述

3.4.2 用注解的方式来创建对象

3.4.2 用注解的方式来注入属性

4. IOC纯注解开发方式 

4.1 概述

4.2 具体书写

5. 小结


1.IOC概述

什么是IOC?

:IOC — Inverse of Control,控制权反转,指将对象的创建权力反转给Spring框架!

我们可以结合下面的场景来思考一下:

在java当中一个类想要使用另一个类的方法,就必须在这个类当中创建这个类的对象,那么可能会出现如下情况, 比如A类当中创建着B对象,B类当中有C对象,C类当中有A对象,这个如果一个类出了问题,那么可能会导致这个框架出现问题。 Spring 将创建对象的权利给了IOC,在IOC当中创建了ABC三个对象吗,那么我们我们其他的类只需要调用集合, 大大的解决了程序耦合性的问题。

控制权反转(Inversion of Control,缩写为IOC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

解决问题:使用IOC可以解决程序耦合性高的问题。

2. IOC容器的底层原理

2.1 概述

IOC的实现,依赖于以下三门技术:

  1. dog4j 解析xml文档
  2. 工厂模式
  3. 采用反射设计模式创建对象

说明:

1.dog4j 解析xml文档:暂时了解即可,没必要知道太多

2.工厂模式:这里简单讲解一下,后面会有专门的工厂模式讲解

工厂模式,指的是:不同的类在相互调用时,不直接调用对方,而是我们创建一个工厂,在工厂中创建这些类,然后调用时是从工厂中调用创建好的,就如同下面这张图片所示:

如果还不是太懂,下面我们来看一个具体的例子:

然后,我们再来看一下用工厂模式怎么写上面的这里例子:

 如上图所示,A调用创建B的工厂BFactory,然后BFactory创建B,这样就不用在A中直接创建B了。这就是一种简单的工厂模式。

第一种方法,A类调用B类就必须自己在自己的内部新建B类的对象,这样耦合度很高,而第二种方法,采用工厂模式就能很有效的降低耦合度。

工厂模式,说白了,就是一种降低耦合度的方法。

3.采用反射设计模式创建对象:反射在java基础中讲过,这里不多说。

2.2 上面的三种技术如何实现IOC?

第一步:配置xml文件,配置创建对象

 就如同下图:

 第二步:创建工厂类(代码如下):

public class DemoFactory {
    //利用dom4j得到name所对应的value值
   public static Demo getDemo() throws Exception {
       //利用dom4j得到name所对应的value值
       String value="class路径";
       //通过反射创建对象
       Class clazz = Class.forName(value);
       //返回并创建demo对象
       return (Demo) clazz.newInstance();
   }
}

通过以上两步,我们基本上就可以得到我们所创建的对象。

(上面这些东西的目的,作用,及如何写我也不是太懂)

2.3 IOC(接口)

1. IOC思想是基于IOC容器完成的,IOC的底层就是对象工厂

2. Spring里边提供了IOC容器的实现的两种方式

(1) BeanFactroy:IOC容器是Spring内部的使用接口,不提供给开发人员使用

 注意:BeanFactroy在加载配置文件的时候不会去创建对象,在使用对象的时候才会去创建对象;也就是说,当你运行时,不会创建对象,只有当你调用了它或使用它时,才会创建对象(这是牺牲时间换取空间的做法)

(2)ApplicationContext: BeanFactory接口的子接口,提供了更多更强大的功能,一般由开发人员进行使用

 注意:ApplicationContext在加载配置文件的时候就会把对象创建出来。(这是牺牲空间换取时间的做法,我=我们通常选用这个)

3.Spring框架的Bean管理

3.1 什么是bean管理

什么是bean管理? bean管理,说白了,就是对象的管理;spring对bean的管理就是spring对java对象的管理。

管理什么?spring的bean管理包括以下两个方面:

  1. 创建对象
  2. 注入属性

(1)创建对象,我们前面说了许多,IOC就是干这个的

(2)注入属性,重点说下这个。属性,即类中的全局变量,注入属性,即spring对对象中的变量赋值

3.2 bean管理操作的两种方式

bean管理主要有以下两种方式,即无论是创建对象还是注入属性均有下面的两种方式

  1. 基于xml配置文件的方式实现
  2. 基于注解的方式实现

3.3 基于xml配置文件的方式实现bean管理

下面,我们将来学习一下基于xml配置文件的方式实现创建对象和属性注入两种操作

3.3.1 基于xml方式创建对象

这个前一篇文章讲过,就是IOC,控制权反转,下面给几张图,大家快速想一下过程就行

第一步:创建对象:

第二步:在xml文件中进行配置扫描:

 第三步:写测试方法:

第四步:测试运行:

 注意:工厂在创建对象的时候,默认是执行无参构造方法完成对象

3.3.2 基于xml方式注入属性

  • 依赖注入的概述:

IOC和DI的概念

  1. IOC:Inverse of Control,控制反转,将对象的创建权反转给Spring!!
  2. Dependency Injection,依赖注入,就是注入属性

  • 属性的set方法注入值:

这种方式叫set注入,因为它在属性注入时调用了类中的set方法。下面,我们来看一下具体的书写:

第一步:写类(注意:必须要给每个变量写set方法,代码如下:)

public class User {
    private int age;
    private String name;
    private Demo01 demo01;

    //必须要写每个变量的set方法
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Demo01 getDemo01() { return demo01; }
    public void setDemo01(Demo01 demo01) { this.demo01 = demo01; }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", demo01=" + demo01 +
                '}';
    }
    public void hello(){
        System.out.println("Hello,User!");
    }
}

第二步:进行xml文件中书写属性注入(代码如下):

<!--配置扫描-->
    <!--set注入-->
    <!--使用 property完成属性注入
            name:类里面属性名称
            value:向属性注入值
            ref:对象映射-->
    <bean id="user" class="com.qcby.service.User">
        <property name="age" value="20"/>
        <property name="name" value="张三"/>
        <property name="demo01" ref="demox"/>
    </bean>

截图如下:

说明:

 第17行:property:表示是属性注入,必须放在bean标签内部;name:后面写类中的属性名称;value:写该属性的值;ref:对象映射,也就是特殊字段特殊处理,这里要注意:ref后面接的一定是存在的对象,也就是在这个xml文件中已经扫描配置的对象,不能是没有扫描配置的,这一点特别要注意!

第三步:运行测试(截图如下):

 第17行挺有意思的,大家可以试一下。

  • 属性构造方法的方式注入值

这种方式叫构造方法注入,因为它在属性注入时调用了类中的构造方法。下面,我们来看一下具体的书写:

第一步:在类中写构造方法(代码如下):

public class User {
    private int age;
    private String name;
    private Demo01 demo01;

    //使用构造方法注入要写构造方法!!!
    public User(int age,String name,Demo01 demo011){
        this.age=age;
        this.name=name;
        this.demo01=demo011;
    }

    //必须要写每个对象的set方法
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Demo01 getDemo01() { return demo01; }
    public void setDemo01(Demo01 demo01) { this.demo01 = demo01; }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", demo01=" + demo01 +
                '}';
    }
    public void hello(){
        System.out.println("Hello,User!");
    }
}

第二步:在xml文件中书写属性注入(代码如下):

<bean id="user" class="com.qcby.service.User">
        <constructor-arg name="age" value="18"/>
        <constructor-arg name="name" value="张三"/>
        <constructor-arg name="demo011" ref="demox"/>
    </bean>

 截图如下:

 说明:

第23行:当我们使用set注入时,使用的是property标签;当我们使用构造器注入时,要使用constructor-arg标签;然后的name,value,ref和前面的一样;注意:name后面接的是你构造器中定义的参数名称,不是你全局变量的名称。

第三步:运行测试(截图如下):

上面写的是使用xml进行属性注入的两种方式,即set方法和构造器的方法;但是,当我们的的全局变量发生了变化,那我们又该怎么对它们进行属性注入呢?下面,我们一起来看看 

  • 数组,集合(List,Set,Map)等属性值的注入

这里主要讲的是当你的全局变量中有数组,集合时,我们对其进行属性注入的方式,这里用的是xml注入的set方式,依然是三步走战略

第一步:写类(注意写set方法):

public class CollectionBean {

    private String [] strs;
    private List<String> list;
    private Map<String,String> map;

    public String[] getStrs() { return strs; }
    public void setStrs(String[] strs) { this.strs = strs; }
    public List<String> getList() { return list; }
    public void setList(List<String> list) { this.list = list; }
    public Map<String, String> getMap() { return map; }
    public void setMap(Map<String, String> map) { this.map = map; }

    @Override
    public String toString() {
        return "CollectionBean{" +
                "strs=" + Arrays.toString(strs) +
                ", list=" + list +
                ", map=" + map +
                '}';
    }
}

截图如下:

 第二步:在xml文件中写属性注入(代码如下):

 <bean id="collectionBeans" class="com.qcby.service.CollectionBean">
        <!--给数组赋值-->
        <property name="strs">
            <array>
                <value>A</value>
                <value>B</value>
                <value>C</value>
            </array>
        </property>
        <!--给list赋值-->
        <property name="list">
            <list>
                <value>熊大</value>
                <value>熊二</value>
                <value>熊三</value>
            </list>
        </property>
        <!--给map赋值-->
        <property name="map">
            <map>
                <entry key="aa" value="张三"></entry>
                <entry key="bb" value="李四"></entry>
            </map>
        </property>
    </bean>

截图如下:

说明:

第30行:set方式注入,用property,没啥问题

第31行:因为是给数组注入值的,所以用array标签,并且数组有多个值,所以下面的value可以多写

第39行:因为是给list类型的变量注入值,所以用list标签,可以注入多个值,所以value可以多写

第47行:因为是给map类型的变量注入值,所以用map标签

第48行:map的形式是key-value形,所以注入值的形式也是这种形式,entry标签记住就行,我也不知道是干啥的

第三步:写测试方法,运行测试(截图如下):

小结:上面就是用xml的方式实现了对bean的管理,即实现创建对象和属性注入两方面的内容。实现创建对象就是在xml文件中进行配置扫描,属性注入就是在xml文件中使用property或constructor-arg标签然后写值,其中属性注入分为两种方法即set方法和构造器方法,并且我们特地的说明了一些特殊的变量像集合、类变量的属性注入的方法。

3.4 基于注解的方式实现bean管理

上面我们讲了基于xml配置文件的方式来实现对bean的管理,现在,我们来说一下基于注解的方式来实现对bean的管理。

3.4.1 注解概述

什么是注解?

①:注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值...)

②:使用注解,注解作用在类上面,方法上面,属性上边

③:使用注解的目的:简化XML配置

3.4.2 用注解的方式来创建对象

  • Spring针对Bean管理中创建对象提供的注解

@Component 普通的类(用于普通的类的,没啥实际意义)

@Controller 表现层(针对表现层的)

@Service 业务层(针对业务层的)

@Repository 持久层(针对持久层的,就是Mybatis那一层)

上边四个功能一样,都可以用来创建bean实例,其中@Controller和@Service是比较重要的。

  • 实际书写一下,用注解的方式来创建对象

下面就让我们来实际写一下,如何用注解的方式来创建对象。

第一步:给类加注解(如下图所示):

 第二步:进行注解扫描的配置

 说明:

第11行:这里依然是在xml文件中配置的,但是与之前的配置扫描不同,之前扫描的是类,这里扫描的是注解,要注意一下。

第三步:运行测试:

注意!!!!:

第23行:getBean传入的参数是啥?这里分两种情况。第一种,在注解中没有赋值,那么此时传入的参数就是你类的名称(首字母小写,如果类的首字母已经小写了,那就写类名,为什么?因为用idea创建对象时,敲个空格后面出现的就是你首字母小写的类名)。第二种,在注解中赋值了,那就直接写注解中的值,从此,注解中的名字将代替你类的名字。我们可以看下下面的这种情况。

 其余的类写起来也是大同小异,多练练就会了。

3.4.2 用注解的方式来注入属性

下面我们来看看如何用注解的方式来实现属性注入

  • Spring针对Bean管理中属性注入提供的注解

@Value 用于注入普通类型(String,int,double,Integer等类型)

@Autowired 默认按类型进行自动装配(用于引用类型)

@Qualifier 不能单独使用必须和@Autowired一起使用,强制使用名称注入

@Resource Java提供的注解,也被支持。使用name属性,按名称注入

  • 实际来写一下,用注解的方式来给属性注入值

 下面就让我们来实际写一下,如何用注解的方式来给属性注入值。依然是“三步走”战略

第一步:写类(给类上注解,给属性上注解)代码如下:

@Component(value = "user011")
public class User {
    private int age;
    private String name;
    @Autowired
    private Demo01 demo01;

    //使用构造方法注入要写构造方法!!!
//    public User(int age,String name,Demo01 demo011){
//        this.age=age;
//        this.name=name;
//        this.demo01=demo011;
//    }

    //必须要写每个对象的set方法
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Demo01 getDemo01() { return demo01; }
    public void setDemo01(Demo01 demo01) { this.demo01 = demo01; }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", demo01=" + demo01 +
                '}';
    }
    public void hello(){
        System.out.println("Hello,User!");
    }
}

截图如下:

第二步:在xml中进行注解扫描的配置(截图如下):

 第三步:运行测试(截图如下):

 对整个流程进行做一下说明:

(1)首先明确我们在干什么,我们在用注解的方式来实现Bean管理中的属性注入,所以原本写的xml的方式就要注释掉,避免出现错误

(2)使用注解,所以我们要进行注解扫描

(3)注释掉了xml的方式的语句,而又要使用注解的方式,首先你要生成对象,所以要用到生成类对象的注解

(4)关于属性注入的注解,@Value不多说,@Autowired用与引用类型的属性上,不需要给什么值,它会自动进行匹配,就像我代码写的,那里有个Demo01的类,并且在这个类上,我加了@Component注解,那么也就是说当我运行UserTest时,Demo01这个类也会被创建出来存储起来,用的时候直接被调用(spring干的),然后我在User类里定义了Demo01类型的变量,我用@Autowired给它赋值,那么这个注解就会进行自动匹配,从我的内存中有没有事先创好的类,有那就匹配上,没有就报错

不信,我们可以试一下:

然后,我们解掉一个注解,再运行一下:

 很有意识的,可以自己试一下。

4. IOC纯注解开发方式 

4.1 概述

什么是纯注解开发?

纯注解开发就是不用xml文件,只用注解的方式来写。这也是我们之后写spring的主要方式。

纯注解的方式是微服务架构开发的主要方式,所以也是非常的重要。纯注解的目的是替换掉所有的配置文件。但是需要编写配置类。

常用的注解总结:

@Configuration 声明是配置类

@ComponentScan 扫描具体包结构的

4.2 具体书写

第一步:编写实体类(类的创建和参数注入都要用注解的方式):

代码如下(User类):

@Component(value = "user011")
public class User {
    @Value("20")
    private int age;
    @Value("张三")
    private String name;
    @Autowired
    private Demo01 demo01;
    //使用构造方法注入要写构造方法!!!
//    public User(int age,String name,Demo01 demo011){
//        this.age=age;
//        this.name=name;
//        this.demo01=demo011;
//    }
    //必须要写每个对象的set方法
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Demo01 getDemo01() { return demo01; }
    public void setDemo01(Demo01 demo01) { this.demo01 = demo01; }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", demo01=" + demo01 +
                '}';
    }
    public void hello(){
        System.out.println("Hello,User!");
    }
}

第二步:编写配置类

创建包,命名为config,在这个包里创建类,命名为SpringConfig,然后给类加注解(代码如下):

@Configuration//作用:声明这是一个配置类
@ComponentScan(value = "com.qcby.service") //作用:扫描bean类所在的包
public class SpringConfig {
}

截图如下:

 第三步:写测试方法(代码如下):

@Test
    public void runByZhuJie(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = ac.getBean("user011",User.class);
        user.hello();
        System.out.println(user.toString());

    }

截图如下:

 第四步:运行测试(截图如下): 

没啥难的。

5. 小结

这篇文章我们主要讲了spring的IOC和其对Bean的管理两方面内容。IOC,说白了是一种技术,是一种思想,是spring的一个核心特点,它体现在对bean的管理里面。在对bean的管理里面,我们按内容分,讲了创建对象和属性注入两部分内容,按操作方式分,讲了xml配置的方式和注解的方式两部分。现在一起回想一下,创建对象用xml怎么写,用注解怎么写。属性注入用xml怎么写,用属性注入怎么写。之后,我们讲了IOC的纯注解开发,这也是我们以后写spring的主要方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L纸鸢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值