小仙女细解Spring的IOC

大家好,本仙女又来啦。上两篇博客我们说了说Spring和Springboot的比较。接下来这两篇博客我们对Spring的核心——IOC和AOP进行一下深刻剖析。

IOC是啥?

在这里插入图片描述

概念

IOC是控制反转,我们以Controller层调Service层为例,以前是这样写:

Service service=new Service();

有了IOC之后,我们这样写:

@Autowired
private Service service;

如果我们使用一个依赖类(这里指Service层),需要对其进行创建、拼接、管理、获取等工作,以前是程序员自己操作,现在是交由Spring容器来管理。这就像“手洗衣服”到“全自动洗衣机洗衣服”的进化。

Ioc的内部结构

Spring容器成功启动的3大要素:Bean配置信息、Bean实现类、Spring容器。生产Bean的过程如下:
(1)Bean的配置信息定义了Bean的实现及依赖关系,Spring容器启动时,首先读取Bean配置信息,并在容器中生成一份相应的Bean配置注册表
(2)然后根据注册表加载、实例化Bean,并建立Bean和Bean之间的依赖关系
(3)最后将这些准备就绪的Bean放到Bean缓冲池中,以供外层的应用程序进行调用

ioc、Bean、注入之间的关系?

  • ioc

是一种思想,是一种将依赖类交由spring容器来管理的思想。

  • Bean

依赖类进入到Spring容器中,就叫做Bean。Spring容器中盛放的对象叫做bean。

  • 注入

程序调用Spring容器已经创建好的对象的过程,就叫做注入。

为什么要使用IOC?

因为使用了IOC能实现类和类之间的解耦。如果A类调用B类,A类直接去跟Spring容器要B类就可以了,不用再自己创建、管理等。这样就实现了A类和B类的解耦。在网上看到这个图,觉得很形象,抠下来,分享给大家。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ioc的4种配置方式?

我们在代码中使用ioc有4种方式:基于XML、基于注解、基于java类、基于Groovy DSL。其分别伴随着Spring1.0、2.0、3.0、4.0的产生而产生。

4种方式

  • 基于XML

在XML的配置文件中定义一个bean:

<bean id="car" class="com.demo.simple.Car"/>

其中id为这个bean的名称,通过getBean(“car”)就可以获取这个bean;class为这个bean对应的实现类。
适用场景:
(1)Bean的实现类来源于第三方类库,如DataSource、JDBCTemplate等,因无法在类中标注注解,所以通过XML配置方式较好。
(2)命名空间的配置,如aop、Context等,只能采用XML方式。

  • 基于注解

这种方式是最常用的。接下来会以基于注解的方式详细叙说ioc的使用。
适用场景:
Bean的实现类是当前项目开发的,可以直接在java类中使用基于注解的配置。

  • 基于Java类
  • 基于Groovy DSL

这两种方式的好处是可以通过Java类或Groovy DSL灵活控制Bean初始化过程,如果实例化Bean的逻辑比较复杂,可以考虑这两种方式。平时使用较少。

复合共存

值得一提的是,这4种配置方式可以复合共存,但是如果定义了同一个bean,可能会出现覆盖的情况。比如如果XML和注解定义了同一个bean,会以XML方式为准。这是因为先加载的注解配置,然后再加载的XML配置,所以XML的配置将注解方式覆盖了。

怎么使用IOC?(基于注解)

定义Bean

3个相关注解:@component、@Controller、@Service、@Repository

package com.smart.anno;
import org.springframework.stereotype.Component

@Component("userDao")
public calss UserDao{}

@Component注解在userDao类的声明处对类进行标注,可以被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean。与xml中的以下配置是等效的:

<bean id="userDao" class="com.smart.anno.UserDao">

其中括号里的"userDao"是在为这个bean定义名字,可写可不写,如果不写,这个Bean的名字默认为“userDao”。
其余的3个,分别为表现层controller层,业务层Service层、持久层Dao层的注解。作用和@Component等效,完全可以替代。

扫描Bean

通过context命名空间的component-scan的base-package属性指定一个需要扫描的基类包,spring容器会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。
(1)对包下所有的类都要扫描

<context:component-scan base-package="com.smart.anno">

(2)扫描指定的类

<context:component-scan base-package="com.smart " resource-pattern="anno/*.class"/>

(3)仅扫描实现了某个特定注解的类

<context:component-scan base-package="com.smart">
       <context:include-filter type="regex" expression="com\.smart\.anno.*"/>
       <context:exclude-filter type="aspectj" expression="com.smart..*Controller+"/>
</context:component-scan>

一个< context:component-scan>下可以包括N个< include-filter>和< exclude-filter>元素。

自动装配Bean

可以在成员变更或方法入参处标注@Autowired。其默认按类型匹配的方式在容器中查找匹配的bean。spring容器默认是单实例的。

@Autowired
public void setUserDao(UserDao userDao){
     this.userDao=userDao;
}

(1)即使找不到即使找不到对应的bean,也不要抛出异常

@Autowired(required=false)

(2)有多个匹配的bean时,可以通过@qualifier()限定名称

@Autowired
@qualifier(“userDao”)

(3)如果是对集合类进行标注的话,Spring会将容器中类型匹配的所有Bean都自动注入进来。我们可以使用@Order来决定Bean加载的顺序

@Autowired(required=false)
@Order(value=1)
private List<Plugin> Plugins;

(4)延迟依赖注入,即在Spring容器启动的时候,不会立即注入属性值,而是延迟到调用此属性的时候才会进行注入。实行依赖注入有一个要求:必须在属性及目标Bean上同时加上@Lazy注解

@Lazy
@Autowired
public void setLogDao(LogDao logDao){……}

@Lazy
@Repository
public class LogDao{}

(5)两个同类——@Resource,@Inject
Spring提供了4种自动装配的类型:byName、byType、constructor、autodetect。
@Autowired是按类型匹配注入bean,
@Resource是按名称匹配注入bean,
@Inject也是按类型匹配注入bean,不过其没有required属性

这两个注解不常用,不必在乎

作用范围

Bean的作用范围有5种:singleton、prototype、request、session、globalSession。默认是按singleton(单实例)方式。我们可以使用@Scope注解来显示指定。

@Scope(“prototype”)
@Component
public class Car{}

生命过程方法

我们可以指定Bean的初始化和容器销毁前执行的方法。使用@PostConstruct、@PreDestroy这两个注解。

对IOC的深入理解

Bean的生命周期

在这里插入图片描述

Bean之间的关系

  • 继承
  • 依赖
  • 引用
  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

卡夫卡的熊kfk

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

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

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

打赏作者

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

抵扣说明:

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

余额充值