【Spring】IOC基本用法

2023-09-15 19:25:07

🎈博客主页:🌈我的主页🌈
🎈欢迎点赞 👍 收藏 🌟留言 📝 欢迎讨论!👏
🎈本文由 【泠青沼~】 原创,首发于 CSDN🚩🚩🚩
🎈由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!🌠个人主页



🌟 一、向Spring容器中注册Bean

🌟🌟 1.1、使用MAVEN注入依赖

选择Spring_context,其中Spring-core和Spring-beans都是包含在context中的,core是最基本的模块,beans模块基于core模块,context基于core和beans模块

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.4</version>
        </dependency>
    </dependencies>

🌟🌟 1.2、创建实体类

public class Person {
    private String name;
    private Integer age;
    private Integer gender;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
    ...省略get和set

🌟🌟 1.3、编写beans.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="com.dong.Person" id="person"/>
</beans>

🌟🌟 1.4、从容器获取 Bean

public class demo1 {
    public static void main(String[] args) {
        //这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext cptx = new ClassPathXmlApplicationContext("beans.xml");
        Person person01 = cptx.getBean("person", Person.class);
        Person person02 = cptx.getBean(Person.class);
        Person person03 = (Person) cptx.getBean("person");
        System.out.println(person01);
        System.out.println(person02);
        System.out.println(person03);
    }
}

要注意的是,如果遇到容器中注册有多个类型一样的bean,就不能使用根据类型来注入bean,否则会报错。如果相同类型存在多个 Bean,则会抛出异常
在这里插入图片描述

🌟 二、Bean标签中的id和name属性

bean 标签中,可以设置 id,也可以设置 name,一般来说,这两者没有区别。
如果使用 id 的话,则 id 要符合 XML 中关于 ID 的规范,就不能使用一些特殊字符
规则:

  1. 如果同时使用 id 和 name,则两者都生效
 <bean class="com.dong.Person" id="person" name="person2"/>
  1. id 和 name 不能重复。同一个容器中,Bean 的名称是不能重复的。id 和 name 也不能重名。如果重复使用 BeanName,则会抛出异常:
    在这里插入图片描述
  2. name 可以同时定义多个
<bean class="com.dong.Person"  name="person1,person2,person3"/>
<bean class="com.dong.Person"  name="person1 person2 person3"/>
<bean class="com.dong.Person"  name="person1;person2;person3"/>

这个表示给当前 Bean 同时取了三个名字,分别是 person1,person2,person3。当然,name 之间可以使用逗号分隔,也可以使用空格或者分号分隔。
如果是 id,则含义不同:

<bean class="com.dong.Person"  id="person1,person2,person3"/>

此时,就表示这个 Bean 的名称为person1,person2,person3这个整体。

如果没有设置 id 和 name 属性,默认的 beanName 就是类的全路径

    public static void main(String[] args) {
        //这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext cptx = new ClassPathXmlApplicationContext("beans.xml");
        Person bean = (Person)cptx.getBean("com.dong.Person");
        System.out.println(bean);
       
    }

如果存在多个类的实例,并且多个实例都没有配置 id 和 name,默认情况下,beanName 就是 类的全路径#编号

    public static void main(String[] args) {
     	//这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //这行代码,会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        Person person1 = (Person) ctx.getBean("com.dong.Person");
        Person person2 = (Person) ctx.getBean("com.dong.Person#1");
        Person person3 = (Person) ctx.getBean("com.dong.Person#2");
        System.out.println(person1);
        System.out.println(person2);
        System.out.println(person3);
       
    }

🌟 三、属性注入

🌟🌟 3.1、从容器获取 Bean

这种注入方式,首先是调用类的无参构造方法去创建一个对象出来,然后通过 set 方法为对象的各个属性赋值

🌟🌟🌟 3.1.1、普通属性注入

首先定义 User 类:

public class User {
    private String name;
    private String address;
    private Integer age;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", age=" + age +
                '}';
    }
省略set和get方法...

然后在 Spring 的配置文件中进行配置:

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.javaboy.demo.User" id="user">
        <!--通过 set 方法去注入值,本质上,这里最终会调用到对应的 set 方法-->
        <property name="name" value="javaboy"/>
        <property name="address" value="深圳"/>
        <property name="age" value="99"/>
    </bean>
</beans>

本质上,这里最终会调用到对应的 set 方法。
启动容器:

public static void main(String[] args) {
        //这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //这行代码,会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        //根据名字获取一个 Bean
        User user = ctx.getBean(User.class);
        System.out.println("user = " + user);
    }

需要注意,XML 中配置的属性名,是通过 get/set 方法推断出来的属性名(Java 内省),不是在类中定义的属性名称

🌟🌟🌟 3.1.2、 复杂属性注入

数组、Map、List、Set、Properties、对象
重新定义 User:

public class User {

    private Dog dog;

    private String[] favorites;

    private List<Cat> cats;

    private Map<String, Object> info;

    private Properties job;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", age=" + age +
                ", dog=" + dog +
                ", favorites=" + Arrays.toString(favorites) +
                ", cats=" + cats +
                ", info=" + info +
                ", job=" + job +
                '}';
    }

set和get省略...

在 XML 文件中注入属性值:

        <bean class="com.dong.Dog" id="dog">
                <property name="name" value="小黑"/>
                <property name="age" value="1"/>
        </bean>
        <bean class="com.dong.Cat" id="cat">
                <property name="age" value="2"/>
                <property name="name" value="小米"/>
        </bean>
        <bean class="com.dong.User" id="user">
                <!--通过 set 方法去注入值,本质上,这里最终会调用到对应的 set 方法-->
                <property name="name" value="dong"/>
                <property name="address" value="shanxi"/>
                <property name="age" value="56"/>
                <!--ref 表示引用一个外部的 Bean,一个外部对象-->
                <property name="dog" ref="dog"/>
                <property name="cats">
                        <list>
                                <bean class="com.dong.Cat" name="cat2">
                                        <property name="name" value="xiaobi"/>
                                        <property name="age" value="3"/>
                                </bean>
                                <ref bean="cat"/>
                        </list>
                </property>
                <property name="favorites">
                        <array>
                                <value>羽毛球</value>
                                <value>足球</value>
                                <value>篮球</value>
                        </array>
                </property>
                <property name="info">
                        <map>
                                <entry key="nation" value="汉族"/>
                                <entry key="deu" value="本科"/>
                        </map>
                </property>
                <property name="job">
                        <props>
                                <prop key="slaray">15000</prop>
                                <prop key="engineer">java工程师</prop>
                        </props>
                </property>
        </bean>

🌟🌟 3.2、构造器注入

首先,为 User 类提供构造器:

    public User() {
    }

    public User(String name, String address, Integer age, Dog dog, String[] favorites, List<Cat> cats, Map<String, Object> info, Properties job) {
        this.name = name;
        this.address = address;
        this.age = age;
        this.dog = dog;
        this.favorites = favorites;
        this.cats = cats;
        this.info = info;
        this.job = job;
    }

然后在 XML 中注入即可:

    <bean class="com.dong.Dog" id="dog">
        <property name="name" value="小黑"/>
        <property name="age" value="1"/>
    </bean>
    <bean class="com.dong.Cat" id="cat">
        <property name="age" value="2"/>
        <property name="name" value="小米"/>
    </bean>
    <bean class="com.dong.User" id="user">
        <!--通过下标去设置参数-->
        <!--        <constructor-arg index="0" value="lisi"/>-->
        <constructor-arg name="name" value="dong"/>
        <constructor-arg name="address" value="shanxi"/>
        <constructor-arg name="age" value="10"/>
        <constructor-arg name="dog" ref="dog"/>
        <constructor-arg name="cats">
            <list>
                <bean class="com.dong.Cat" name="cat2">
                    <property name="name" value="xiaobi"/>
                    <property name="age" value="3"/>
                </bean>
                <ref bean="cat"/>
            </list>
        </constructor-arg>
        <constructor-arg name="favorites">
            <array>
                <value>羽毛球</value>
                <value>足球</value>
                <value>篮球</value>
            </array>
        </constructor-arg>
        <constructor-arg name="info">
            <map>
                <entry key="nation" value="汉族"/>
                <entry key="deu" value="本科"/>
            </map>
        </constructor-arg>
        <constructor-arg name="job">
            <props>
                <prop key="position">Java工程师</prop>
                <prop key="salary">15000</prop>
            </props>
        </constructor-arg>
    </bean>

🌟🌟 3.3、p 名称空间注入

<bean class="com.dong.Dog" id="dog02" p:name="小黄" p:color="黄色"/>

🌟 四、属性自动注入

bean 标签中的 autowire 属性有五种

取值含义
no默认取值即此。表示不做自动注入,如果有需要注入的值,需要用户明确的手动去指定注入
byName这个会分析当前 Bean 中的属性,然后去 Spring 容器中查找到同名的属性,并调用 set 方法给该 Bean 中对应的属性赋值
byType这个会分析当前 Bean 中的属性,然后去 Spring 容器中查找到同类型的属性,并调用 set 方法给该 Bean 中对应的属性赋值。但是需要注意,如果使用这一种,则去查找的 Bean 只能存在一种有效类型
constructor这个会找到合适的构造方法,通过构造方法给对应的属性注入值
default这个表示使用父标签中的定义处理
<beans default-autowire="constructor">
    <bean class="com.dong.Cat" id="cat">
        <property name="name" value="小花"/>
        <property name="age" value="10"/>
    </bean>
    <bean class="com.dong.Cat" id="cat2">
        <property name="name" value="小菜"/>
    </bean>
    <bean class="com.dong.User" id="user" autowire="default">
        <property name="name" value="张三"/>
        <property name="age" value="99"/>
    </bean>
</beans>

🌟 五、配置文件加载

public class demo01 {
    public static void main(String[] args) {
        FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext("src/main/resources/beans.xml");
        User user = ctx.getBean(User.class);
        System.out.println("user = " + user);
    }
}
  • FileSystemXmlApplicationContext:这个是从当前项目根目录下开始去加载配置文件

  • ClassPathXmlApplicationContext:这个是去 classpath 下查找配置文件

🌟 六、Java 代码配置

public class JavaConfig {

    /**
     * 这个就表示将当前方法的返回值注册到 Spring 容器中,默认情况下,方法名就是 beanName
     * 如果想自定义 BeanName,则可以在 @Bean 注解中进行定义。
     */
    @Bean("u1")
    User user1(Dog dog) {
        User user = new User();
        user.setName("javaboy");
        user.setAge(99);
        user.setDog(dog);
        return user;
    }

    @Bean
    Dog dog() {
        Dog dog = new Dog();
        dog.setName("阿黄");
        dog.setAge(8);
        return dog;
    }

}
  • 当前类没有添加 @Configuration注解
  • 在一个 @Bean标记的方法中,调用另一个 @Bean标记的方法,对于当前这种情况,默认会直接再次执行该方法,从而导致某一个 Bean 被初始化两次
  • 可以在 Bean 方法中,添加参数,Spring 容器在初始化的时候,会自动从 Spring 容器中查找并处理这个参数
更多推荐

使用kubeadm快速部署一个k8s集群

0.前置准备准备好3台服务器,一台作为master,另外两台作为worker节点。3台服务器网络互通,os是centos-7.91.设置服务器操作关闭服务器防火墙:systemctlstopfirewalld永久关闭selinux:sed-i's/enforcing/disabled/'/etc/selinux/con

K8S:Yaml文件详解

目录一.Yaml文件详解1.Yaml文件格式2.YAML语法格式二.Yaml文件编写及相关概念1.查看api资源版本标签2.yaml编写案例(2)Deployment类型编写nginx服务(3)k8s集群中的port介绍(5)快速编写yaml文件(6)案例:自主式创建service并关联上面的pod(7)Podyaml

基于Levenberg-Marquardt算法的声源定位matlab仿真

目录1.算法运行效果图预览2.算法运行软件版本3.部分核心程序4.算法理论概述5.算法完整程序工程1.算法运行效果图预览2.算法运行软件版本matlab2022a3.部分核心程序....................................................................%ML

Spring Boot虚拟线程的性能还不如Webflux?

早上看到一篇关于SpringBoot虚拟线程和Webflux性能对比的文章,觉得还不错。内容较长,抓重点给大家介绍一下这篇文章的核心内容,方便大家快速阅读。测试场景作者采用了一个尽可能贴近现实操作的场景:从授权头信息中提取JWT验证JWT并从中提取用户的Email使用用户的Email去MySQL里执行查询返回用户记录测

K8S群集调度

K8S群集调度一、调度约束1.概述2.Pod启动典型创建过程(工作机制)3.调度过程4.Predicate的常见的算法5.常见的优先级选项6.指定调度节点:二、亲和性1.节点亲和性2.Pod亲和性3.键值运算关系4.示例5.Pod亲和性与反亲和性6.使用Pod反亲和性调度三、污点(Taint)和容忍(Toleratio

什么是Progressive Web App(PWA)?它们有哪些特点?

聚沙成塔·每天进步一点点⭐专栏简介⭐渐进式WebApp简介⭐PWAs的主要特点⭐总结⭐写在最后⭐专栏简介前端入门之旅:探索Web开发的奇妙世界欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供

利用Linux虚拟化技术实现资源隔离和管理

在现代计算机系统中,资源隔离和管理是非常重要的,特别是在多租户环境下。通过利用Linux虚拟化技术,我们可以实现对计算资源(如CPU、内存和存储)的隔离和管理,以提供安全、高效、稳定的计算环境。下面将详细介绍如何利用Linux虚拟化技术实现资源隔离和管理。一、什么是Linux虚拟化技术?Linux虚拟化技术是指在Lin

猫头虎博主第四期赠书活动:《精通Go语言:(第2版) 》

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

神经网络 05(损失函数)

一、损失函数在深度学习中,损失函数是用来衡量模型参数的质量的函数,衡量的方式是比较网络输出和真实输出的差异,损失函数在不同的文献中名称是不一样的,主要有以下几种命名方式:损失函数(lossfunction)代价函数(costfunction)目标函数(objectivefunction)误差函数(errorfuncti

【Vue】模板语法,事件处理器及综合案例、自定义组件、组件通信

一、事件处理器我们之前事件监听可以使用v-on指令1、事件修饰符在Vue中我们通过由点(.)表示的指令后缀来调用修饰符,比如:.stop:阻止事件冒泡。当事件触发时,该修饰符将停止事件进一步冒泡到父元素。相当于调用了event.stopPropagation().prevent:阻止默认事件。默认情况下,某些元素会有默

python正则表达(06)

python正则表达(06)文章目录python正则表达(06)1正则表达式概念2正则的三个基础方法2.1match、search、findall三个基础方法2.2re.match()函数2.2.1re.match(匹配规则,被匹配字符串)2.2.2验证是否开头匹配,match是匹配开头,后面的是不匹配2.3re.se

热文推荐