Spring IoC容器与Bean管理(二)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: Spring IoC容器与Bean管理

2.XML管理对象(Bean)


在我们Spring管理的时候,说起对象,都是一个个的JavaBean。JavaBean并不是一项特殊的技术,它就是对于Java的可重用的对象的一些编码的要求。如属性私有,构造方法,getter和setter方法等。而Spring IoC容器中,管理的就是这一个个的JavaBean。所以我以后就用Bean来指代容器中的对象。


spring对于Bean的管理,包含了3种配置方式。

第一种是基于XML配置Bean、第二种是基于注解配置Bean、第三种是基于Java代码配置Bean。


这三种配置bean的方式的本质都是一样的,都是告诉Spring IoC 容器如何实例化和管理这些Bean。只是他们的表现形式不一样而已。


下面就来讲解基于XML来管理对象。还是回到上面的例子。


f6a40fc394044539a1eef9134e1e8608.png


applicationContext.xml这个文件名是约定俗称的,一般都叫这个名字。在配置文件中,所有的对象都统一使用Bean这个标签。里面的id属性指的是指定的类被IoC容器实例化后,对象的(唯一标识)名字是什么,这里我们叫它sweetApple ,class指定要被IoC容器实例化的那个类。至于<bean>标签里面的<property>并不是必须的。在后面讲解属性注入的时候再详细解释。


2b073f503baa4de881fbfd215bdf7873.png


spring提供了ApplicationContext来创建IoC容器。ApplicationContext是一个接口,有很多具体的实现类,其中ClassPathXmlApplicationContext这个类就实现了从当前类路径去读取指定的xml文件并解析加载的过程。ClassPathXmlApplicationContext是最常用的核心类之一。当运行了这一段代码,就意味着在我们Java的运行内存中保存了IoC容器,并且IoC容器根据刚才的配置,创建了对应的对象,并对这些对象进行管理。


ClassPathXmlApplicationContext允许加载多个xml文件的,采用传入字符串数组的形式。


        String[] configLocations=new String[]{"classpath:applicationContext.xml","classpath:applicationContext-1.xml"};
        ApplicationContext context=new ClassPathXmlApplicationContext(configLocations);


3.三种XML实例化Bean的配置方式:


1.基于默认无参构造方法实例化对象

2.基于静态工厂实例化对象

3.基于工厂实例方法来实例化对象


基于默认无参构造方法实例化对象


创建一个名为s02的空的Maven项目,引入依赖spring-context。和之前一样创建entity包,里面创建苹果类Apple和孩子类Child类。

然后编写applicationContext.xml配置文件。


<?xml version="1.0" encoding="UTF-8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--bean标签默认通过类的默认无参构造方法创建对象-->
    <bean id="apple1" class="com.haiexijun.entity.Apple">
    </bean>
</beans>


在里面配置了一个Apple的对象,名字为apple1。

然后在Apple类的无参默认的构造方法里面添加一行代码:


public Apple() {
        System.out.println("Apple对象已创建,"+this);
    }


在有main方法的java类里编写如下代码运行,会发现Apple的默认无参构造方法


package com.haiexijun.app;
import com.haiexijun.entity.Apple;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringApplication {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }
}

运行结果:


d3e965092696469da128c8bce94e5a1a.png


那如果要用带参数的构造方法来创建对象该怎么做,下一节在进行详解。


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


88b95104969348979915c341ba8779f0.png


在bean下面插入一个<constructor-arg>的子标签,在这子标签中,我们可以通过设置name属性来为带参构造方法的指定参数,用value属性来设置对应的值。


除了可以用name属性来指定构造方法的参数外,还可以用index属性来设置指定的参数,用value属性来设置值。index说明参数的前后位置。index从0开始。


ad53428d836b45b98e23598c9c7208cc.png


实际工作中,更推荐第一种方式来传参。这里就不作演示了。但有参构造方法有多个时,比如一个类有一个3个参数的构造方法,有一个4个参数的构造方法。我们在bean中传入几个参数,程序就调用对应数量参数的构造方法。


基于静态工厂实例化对象


其实这种实例化对象的方式用的不多,主要还是构造方法来实例化对象。我们通常说的工厂,其实指的是工厂模式。作为工厂模式,他的根本用途就是隐藏创建类的细节。通过一个额外的工厂类来组织创建我们需要的对象。按照工厂的表现形式,又可以分为静态工厂和工厂实例。


我们通过代码案例来了解和体验基于静态工厂实例化对象。


创建一个factory子包,保存工厂类。然后创建一个java类AppleStaticFactory。里面有一个方法,用于创建甜苹果。


package com.haiexijun.factory;
import com.haiexijun.entity.Apple;
public class AppleStaticFactory {
    public static Apple createSweetApple(){
        Apple apple=new Apple();
        apple.setTitle("红富士");
        apple.setOrigin("欧洲");
        apple.setColor("红色");
        return apple;
    }
}


然后在applicationContext.xml中调用这个工厂创建对象。


    <!--利用静态工厂获取对象-->
    <bean id="apple4" class="com.haiexijun.factory.AppleStaticFactory" factory-method="createSweetApple"/>


这里你可能会问了,这种方式创建对象不久和以前传统new创建对象一样吗?其实是有很大的不同的,工厂的职责就是通过静态方法来创建对象,隐藏创建对象的细节。里面如何创建对象,对于我们来说是不可见的。创建者只需要知道但调用了工厂类的createSweetApple后,会创建一个甜苹果就行了。


基于工厂实例方法来实例化对象


工厂实例方法创建对象是指IoC容器对工厂类进行实例化并调用对应的工厂实例方法创建对象的过程。


在factory包下创建一个java类AppleFactoryInstance , 里面的方法没有static关键字。


package com.haiexijun.factory;
import com.haiexijun.entity.Apple;
/**
 * 工厂实例方法创建对象是指IoC容器对工厂类进行实例化并调用对应的工厂实例方法创建对象的过程。
 */
public class AppleFactoryInstance {
    public Apple createSweetApple(){
        Apple apple=new Apple();
        apple.setTitle("红富士");
        apple.setOrigin("欧洲");
        apple.setColor("红色");
        return apple;
    }
}


在applicationContext.xml中调用这个工厂创建对象,这里要创建2个bean。

    <!--利用工厂实例方法获取对象-->
    <bean id="factoryInstance" class="com.haiexijun.factory.AppleFactoryInstance"/>
    <bean id="apple5" factory-bean="factoryInstance" factory-method="createSweetApple"/>


有一说一,随着spring的功能越来越强大,在实际的使用环境中,基于工厂来创建对象的这种情况越来越少了。我们只做一般性了解就可以了。


    <!--利用工厂实例方法获取对象-->
    <bean id="factoryInstance" class="com.haiexijun.factory.AppleFactoryInstance"/>
    <bean id="apple5" factory-bean="factoryInstance" factory-method="createSweetApple"/>


4.从IoC容器中获取Bean


97859aee073d45258660d321af2611b3.png


xml文件的bean有id和name属性。


id与name属性的相同点有:

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


但是他们也有很多不同点:id要求更加严格,一次只能定义一个对象标识。name更为宽松,一次允许定义多个对象标识。我们推荐使用id。


注意:id与name的命名要求要有意义,按驼峰命名书写。


了解:在没有进行设置id和name的情况下


    <bean class="com.haiexijun.entity.Apple">
        <constructor-arg index="0" value="红富士"/>
        <constructor-arg index="1" value="红色"/>
        <constructor-arg index="2" value="欧洲"/>
        <constructor-arg index="3" value="12.1"/>
    </bean>


使用全类名来作为bean的标识.


Apple apple3 = context.getBean("com.haiexijun.entity.Apple",Apple.class);


5.路径表达式


fa26343e4efc48e2a7431bbe49cf30ca.png

作为ClassPathXmlApplicationContext的参数,要求传入一个表达式。这个表达式的含义是去加载我们当前类路径下名为applicationContext的xml文件。


在源代码目录下的resources并不是我们的类路径,而是项目生成的target目录下的classes目录下才是真是的类路径。


21178957812745a4a3c3685bb5a18f84.png


ClassPathXmlApplicationContext可以加载多个配置文件,创建一个String数组,按顺序来加载xml配置文件。


8a5357b197e849089f8e1d432fba297a.png

ad09713e9e9c4c9fa859cbcf28707e5b.png


相关文章
|
18天前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
1月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
72 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
25天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
17天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
31 0
|
1月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
87 1
|
1月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
71 0
|
1月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
48 0
|
13天前
|
Kubernetes Cloud Native Docker
云原生时代的容器化实践:Docker和Kubernetes入门
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术成为企业提升敏捷性和效率的关键。本篇文章将引导读者了解如何利用Docker进行容器化打包及部署,以及Kubernetes集群管理的基础操作,帮助初学者快速入门云原生的世界。通过实际案例分析,我们将深入探讨这些技术在现代IT架构中的应用与影响。
55 2
|
3天前
|
Kubernetes Linux 开发者
深入探索容器化技术——Docker 的实战应用
深入探索容器化技术——Docker 的实战应用
23 5
下一篇
无影云桌面