springIOC创建对象的方式--spring容器中的注入

Spring IOC 本质:IOC = Inversion of Control,控制反转

spring容器=bean

把对象的创建、依赖管理、生命周期控制权,从程序员自己手动 new,交给 Spring 容器统一管理。

传统写法(正控:程序员掌控一切)

c 复制代码
// 自己手动new对象
UserService service = new UserService();
// 自己手动给属性赋值、创建依赖对象
UserDao dao = new UserDao();
service.setDao(dao);

控制权在你代码手里:你想什么时候 new、怎么赋值、什么时候销毁,全由代码硬编码决定。

IOC 写法(反转:容器接管控制权)

你只在配置 / 注解里告诉 Spring:需要哪些类、谁依赖谁。

Spring 容器自动:

创建实例对象

自动装配依赖(自动 set 注入 / 构造注入)

管理对象单例 / 多例、初始化、销毁

对象生命周期的控制权,反转交给了 IoC 容器,这就是控制反转。

  1. 核心两大核心职能,就是 IOC 容器的本体
    ① 实例化:Bean 工厂
    容器就是一个超大 Map 容器:Map<bean名称, 实例对象>
    启动时扫描所有组件,提前创建好对象存入 Map,后续你用 getBean() 直接从容器里取,不用自己 new。
    ② 依赖注入 DI(IOC 最核心落地手段)
    DI = Dependency Injection 依赖注入
    IOC 是思想,DI 是实现 IOC 的具体方式。
    容器自动把一个类需要的其他对象,自动注入进去,不用手动编码装配依赖
    Spring IoC 创建 Bean 对象的 5 种常用方式:

传统的创建对象方式

1、new User();//通过无参构造实例化化对象

2、new User(name);//通过有参构造实例化化对象

spring容器(bean)创建对象(实例化对象)

一、无参构造方法创建(默认最基础方式)

规则

Spring 会默认调用类无参构造函数实例化对象,XML / 注解方式默认都是此方式。

clike 复制代码
<!-- 只指定类,底层自动调用无参构造 -->
<bean id="user" class="com.pojo.User"/>

前提:类必须存在无参构造,如果只写了有参构造、没写无参,直接报错。

二、有参构造器创建(构造注入)

方式 1:下标索引赋值

csharp 复制代码
<bean id="user" class="com.pojo.User">
    <!-- index 对应构造方法参数位置,从0开始 -->
    <constructor-arg index="0" value="张三"/>
    <constructor-arg index="1" value="18"/>
</bean>

方式 2:参数名匹配

bash 复制代码
<constructor-arg name="username" value="李四"/>

方式 3:参数类型匹配

c 复制代码
<constructor-arg type="java.lang.String" value="王五"/>

依赖注入

1、构造器注入

2、set方式注入(重点)

XML:set 注入、构造注入;

注解:@Autowired按类型、@Resource按名称、@Value注入配置;

DI 本质:容器帮你给类的依赖属性赋值。

三、DI 依赖注入(Dependency Injection)超全详解

DI = Dependency Injection 依赖注入

IOC 是思想(控制反转):把对象创建、依赖管理交给容器;

DI 是 IOC 的具体实现手段:容器主动将当前类需要的依赖对象,自动赋值注入进去,不用自己new依赖。

二、Spring 4 种主流注入方式

  1. Setter 注入(标签,最常用)
    条件
    类中必须提供 setXxx () 方法,Spring 通过反射调用 set 方法赋值。
bash 复制代码
<!-- 1. 普通基本类型/字符串 -->
<bean id="user" class="com.pojo.User">
    <property name="username" value="张三"/>
    <property name="age" value="18"/>
</bean>

<!-- 2. 注入容器中其他Bean对象(ref引用) -->
<bean id="userDao" class="com.dao.UserDao"/>
<bean id="userService" class="com.service.UserService">
    <!-- name对应setDao,ref指向另一个bean的id -->
    <property name="dao" ref="userDao"/>
</bean>
  1. 构造器注入()
    条件
    类提供带参数构造方法,容器实例化 Bean 时直接通过构造方法传参创建对象。
cpp 复制代码
<bean id="user" class="com.pojo.User">
    <!-- 方式1:按构造参数下标(从0开始) -->
    <constructor-arg index="0" value="李四"/>
    <!-- 方式2:按参数名匹配 -->
    <constructor-arg name="age" value="22"/>
    <!-- 方式3:按参数类型匹配 -->
    <constructor-arg type="int" value="22"/>
    <!-- 注入其他Bean -->
    <constructor-arg name="dao" ref="userDao"/>
</bean>
c 复制代码
 <!--p命令空间注入,直接注入属性值对比传统的set注入 -->
    <bean id="user2" class="com.cn.User" p:name="p标签写法" p:gae="20"/>
    <!--c命令空间注入,通过构造器注入属性值对比传统的构造注入-->
    <bean id="user1" class="com.cn.User" c:name="构造器" c:gae="30"/>

两种对比:

c 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
    1、语法:p:属性名="值"

    <bean id="student" class="com.cn.Student"
          p:name="张三"
          p:age="20"/>
    等价写法

    <bean id="student" class="com.cn.Student">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
    </bean>

    2、 引用其他 Bean 对象(对象依赖)
    p:属性名-ref="目标beanId"

    <bean id="address" class="com.cn.Address" p:city="乌鲁木齐"/>

    <bean id="student" class="com.cn.Student"
          p:name="李四"
          p:address-ref="address"/>

等价写法
<property name="address" ref="address"/>
    -->
    <!--1、传统写法-->

    <bean id="adder" class="com.cn.Adderss"/>
    <bean id="user" class="com.cn.User">
        <property name="name" value="传统写法"/>
        <property name="gae" value="20"/>
    </bean>

    <!--p:写法
    1、语法:p:属性名="值"
reference:ref==引用

    <bean id="student" class="com.cn.Student"
          p:name="张三"
          p:age="20"/>-->

    <!--p命令空间注入,直接注入属性值对比传统的set注入 -->
    <bean id="user2" class="com.cn.User" p:name="p标签写法" p:gae="20"/>
    <!--c命令空间注入,通过构造器注入属性值对比传统的构造注入-->
    <bean id="user1" class="com.cn.User" c:name="构造器" c:gae="30"/>


    <bean id="stu" class="com.cn.User">
        <!-- 第一个参数 -->
        <constructor-arg value="小明"/>
        <!-- 第二个参数 -->
        <constructor-arg value="18"/>
    </bean>
    <bean id="stu1" class="com.cn.User">
        <!-- 第一个参数 -->
        <constructor-arg value="小明"/>
        <!-- 第二个参数 -->
        <constructor-arg value="18"/>
    </bean>
    <bean id="stu2" class="com.cn.User">
        <constructor-arg index="0" value="小红"/>
        <constructor-arg index="1" value="20"/>
    </bean>
</beans>
  1. 字段注入(注解开发主流,直接给成员变量赋值)
    不需要 set / 构造方法,直接在属性上加注解,底层反射暴力赋值。
    ① @Autowired(Spring 原生,按类型 byType 注入)
c 复制代码
@Service
public class UserService {
    // 直接注入,不需要set方法
    @Autowired
    private UserDao userDao;
}

③ @Value 注入普通字面量 / 配置文件值

bash 复制代码
// 直接写死值
@Value("小明")
private String name;
// 读取properties配置文件
@Value("${db.url}")
private String url;
相关推荐
2601_962072212 小时前
SpringMVC进阶(自定义拦截器以及异常处理)
java
2601_962073812 小时前
Spring全面详解(基础版)
java·后端·spring
谢亮_vipxieliang3 小时前
ValidX分组验证详解:不同场景使用不同验证规则
java·spring boot·后端·spring cloud·eclipse·hibernate
wuminyu4 小时前
深入剖析 Panama Off-heap 的性能损耗与开销
java·linux·c语言·jvm·c++
pnoker4 小时前
IoT DC3 AI 能力:Agentic Center 的设计与边界
java·人工智能·物联网·大模型·spring ai
凤山老林4 小时前
Spring Boot 集成 Spring Vault:集中式密钥管理与动态凭证轮换
spring boot·后端·spring·vault·集中式秘钥管理
xiaoqiMikko4 小时前
一条 CVSS 9.0 的 RCE,advisory 里没写修复版是哪个 —— fastjson 16723 的字段考古
java·安全
程序员贺加贝4 小时前
一次 SaaS ERP 主数据生命周期设计:Policy、PreCheck 与结构化阻断原因
java·后端·架构·saas
catino5 小时前
spring-Bean
java·后端·spring
深入云栈5 小时前
Netty 4.2.x 源码深度解析 (十一):EventExecutor 业务线程池 —— 防止 IO 线程阻塞的并发模型
java·后端