Spring IoC容器于Bean管理



初识Spring

IoC控制反转

IoC 控制反转,全称 Inverse of Control,是一种设计理念。

由代理人来创建与管理对象,消费者通过代理人来获取对象。

IoC 的目的是降低对象之间的直接耦合。

加入IoC容器将对象统一管理,让对象关联变为弱耦合。

image-20220731213622316

DI依赖注入

Ioc 是设计理念,是现代程序设计遵循的标准,是宏观目标。

DI (Dependency Injection) 是具体技术实现,是微观实现。

介绍 Spring

Spring 的含义

Spring 可从狭义与广义两个角度看待

狭义的 Spring 是指Spring框架(Spring Fremework)

广义的 Spring 是指Spring生态体系

狭义的 Spring 框架

Spring 框架是企业开发复杂性的 一站式 解决方案

Spring 框架的核心是 IoC容器AOP面向切面编程

Spring IoC负责创建与管理系统对象,并在此基础上扩展功能

广义的 Spring 生态体系

image-20220731215604086

Spring官方文档5.3.22:Spring Framework Documentation

Spring IoC容器

IoC容器是Spring生态的地基,用于统一创建于管理对象依赖

image-20220731221641490

Spring IoC容器职责

对象的控制权交由==第三方==统一管理(IoC控制反转)

利用Java==反射==技术实现==运行时==对象创建于关联(DI依赖注入)

基于配置提高应用程序的可维护性与扩展性

使用XML方式实现Spring IoC

8cf2803942250cd8a53f9beace0f6772

初始化IoC容器

三种配置方式:

  1. 基于XML配置Bean
  2. 基于注解配置Bean
  3. 基于Java代码配置Bean

基于XML配置Bean

<bean id="sweetApple" class="com.hua.spring.ioc.entity.Apple">
    <property name="title" value="红富士"></property>
    <property name="color" value="红色"></property>
    <property name="origin" value="欧洲"></property>
</bean>
// 创建IoC容器并根据配置文件创建对象
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

利用带参构造方法实例化对象

<bean id="sweetApple" class="com.hua.spring.ioc.entity.Apple">
    <!-- 没有 constructor-arg 则代表调用默认构造的方法实例化 -->
    <constructor-arg name="title" value="红富士" />
    <constructor-arg name="color" value="红色" />
    <constructor-arg name="origin" value="欧洲" />
</bean>
<bean id="sweetApple" class="com.hua.spring.ioc.entity.Apple">
    <!-- 利用构造方法参数位置实现对象实例化 -->
    <constructor-arg index="0" value="红富士" />
    <constructor-arg index="1" value="红色" />
    <constructor-arg index="2" value="欧洲" />
</bean>

基于工厂实例化创建对象

/**
 * 静态工厂通过静态方法创建对象,隐藏创建对象的细节
 */
public class AppleStaticFactory {
    public static Apple createSweetApple(){
        Apple apple = new Apple();
        apple.setTitle("红富士");
        apple.setColor("红色");
        apple.setOrigin("欧洲");
        return apple;
    }
}
//...
<bean id="book3" class="com.hua.spring.ioc.factory.AppleStaticFactory" factory-method="createSweetApple"/>
/**
 * 工厂实例方法创建对象是指IoC容器对工厂类进行实例化并调用对应的实例方法创建对象的过程
 */
public class AppleFactoryInstance {
    public Apple createSweetApple(){
        Apple apple = new Apple();
        apple.setTitle("红富士");
        apple.setColor("红色");
        apple.setOrigin("欧洲");
        return apple;
    }
}
// ...
<!--利用工厂实例方法获取对象-->
    <bean id="appleFactoryInstance" class="com.hua.spring.ioc.factory.AppleFactoryInstance"/>
        <bean id="apple4" factory-bean="appleFactoryInstance" factory-method="createSweetApple"/>

从IoC容器获取Bean

// 推荐使用第一种方式
Book book2 = context.getBean("book2", Book.class);
Book book3 = (Book)context.getBean("book2");

id与name属性相同点

  • bean id与name都是设置对象在IoC容器中唯一标识
  • 两者在同一配置文件中都不允许出现重复
  • 两者允许在多个配置文件中出现重复,新对象覆盖旧对象

id与name属性区别

  • id要求更为严格,一次只能定义一个对象标识
  • name更为宽松,一次允许定义多个对象标识
  • tips: id与name的命名要求有意义,按驼峰命名书写
  • 在没有id与name的bean默认使用类名全称作为bean标识

路径表达式用法

加载单个配置文件

// 创建IoC容器并根据配置文件创建对象
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");

加载多个配置文件

String[] configLocations = new String[]{"classpath:applicationContext.xml","classpath:applicationContext-1.xml"}
ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
表达式示例说明
classpath:config.xml扫描classpath根路径(不包含jar)的config.xml
classpath:com/imooc/config.xml扫描classpath下(不包含jar)com.imooc包中的config.xml
classpath*:com/imooc/config.xml扫描classpath下(包含jar)com.imooc包中的config.xml
classpath:config-*.xml扫描classpath根路径下所有以config-开头的XML文件
classpath:com/**/config.xml扫描com包下(包含任何子包)的config.xml
file:c:/config.xml扫描c盘根路径config.xml

利用setter实现对象依赖注入

  • 依赖注入是指运行时将容器内对象利用反射赋给其它对象的操作
  • 基于setter方法注入对象
  • 基于构造方法注入对象

利用setter实现静态数值注入

<bean id="sweetApple" class="com.hua.spring.ioc.entity.Apple">
    <!-- IoC容器自动利用反射机制运行时调用SetXXX方法为属性赋值 -->
    <constructor-arg name="title" value="红富士" />
    <constructor-arg name="color" value="红色" />
    <constructor-arg name="origin" value="欧洲" />
</bean>

利用setter实现对象注入

<bean id="lily" class="com.hua.spring.ioc.entity.Child">
    <!--利用setter实现对象注入-->
    <property name="name" value="莉莉"/>
    <!--利用ref注入依赖对象-->
    <property name="apple" ref="sweetApple"/>
</bean>

注入集合对象

注入List

<bean id="..." class="...">
    <property name="someList">
        <list>
            <value>具体值</value> //或
            <ref bean="beanId"></ref>
        </list>
    </property>
</bean>

注入Set

<bean id="..." class="...">
    <property name="someSet">
        <set>
            <value>具体值</value> //或
            <ref bean="beanId"></ref>
        </set>
    </property>
</bean>

注入Map

<bean id="..." class="...">
    <property name="someMap">
        <map>
            <entry key="k1" value="v1"></entry> //或
            <entry key="k2" value-ref="beanId"></entry>
        </map>
    </property>
</bean>

注入Properties

<bean id="..." class="...">
    <property name="someProperties">
        <props>
            <prop key="k1">v1</prop>
            <prop key="k2">v2</prop>
        </props>
    </property>
</bean>

查看容器内对象

getBeanDefinitionNames() 方法查看当前容器内所有对象

image-20220804150435332

Bean对象的作用域及生命周期

bean scope属性

bean scope属性用于决定对象何时被创建于作用范围

bean scope配置将影响容器内对象的数量

默认情况下bean会在IoC容器创建后自动实例化,全剧唯一

scope用法
<bean id="xxx" class="com.hua.spring.ioc.entity.xxx" scope="prototype" />
scope属性
image-20220804160646544

singleton 在容器是 单利多线程 执行,存在 线程安全风险

image-20220804162717834

bean声明周期

image-20220804234147963

使用注解方式实现Spring IoC

基于注解的优势

  1. 摆脱繁琐的XML形式的bean与依赖注入配置
  2. 基于“声明式”的原则,更适合轻量级的现代企业应用
  3. 让代码可读性变得更好,研发人员拥有更好的开发体验

三类注解

  1. 组件类型注解:声明当前类的功能与职责
  2. 自动装配注解:根据属性特征自动注入对象
  3. 元数据注解:更细化的辅助IoC容器管理对象的注解

四种组件类型注解

注解说明
@Component组件注解,通常注解,被该注解描述的类将被IoC容器管理并实现
@Controller语义注解,说明当前类是MVC应用中的控制器类
@Service语义注解,说明当前类是Service业务服务类
@Repository语义注解,说明当前类用于业务持久层,通长描述对应的Dao类
<!-- XML配置开启组件扫描,才能使用注解 -->
<context:component-scan base-package="com.hua">
    <context:exclude-filter type="regex" expression="com.hua.exl.*" />
</context:component-scan>

自动装配与Autowired注解

image-20220806142759245

Resource注解按名称装配

  1. @Resource设置name属性,则按name在IoC容器中将bean注入
  2. @Resource未设置name属性
    1. 以属性名作为bean name在IoC容器中匹配bean,如有匹配则注入
    2. 按属性名未匹配,则按类型进行匹配,同@Autowired,需加入@Primary解决类型冲突

使用建议:在使用@Resource对象时推荐设置name或保证属性名与bean名称一致

元数据注解

注解说明
@Primary按类型装配时出现多个相同类型对象,拥有此注解对象优先被注入
@PostConstruct描述方法,相当于XML中init-method配置的注解版本
@PreDestroy描述方法,相当于XML中destroy-method配置的注解版本
@Scope设置对象的scope属性
@Value为属性注入静态数据

Java Config配置IoC容器

Java Config的优势:

  • 完全摆脱XML的束缚,使用独立Java类管理对象的依赖
  • 注解配置相对分散,利用Java Config可对配置集中管理
  • 可以在编译时进行依赖检测,不容易出错
注解说明
@Configuration描述类,说明当前类是Java Config配置类,完全替代XML文件
@bean描述方法,方法返回对象将被IoC容器管理,beanId默认为方法名
@ImportResource描述类,加载静态文件,可使用@Value注解获取
@ComponentScan描述类,通XML的标签

Spring与JUnit4整合

  • Spring Test是Spring中用于测试的模块
  • Spring Test对JUnit单元测试框架有良好的整合
  • 通过Spring Test可在JUnit在单元测试时自动初始化IoC容器

Spring于JUnit4整合过程

  • Maven工程依赖spring-test
  • 利用@RunWith@ContextConfiguration描述测试用例类
  • 测试用例类从容器获取对象完成测试用例的执行
image-20220806191541214
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片