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;
相关推荐
ZJH__GO5 小时前
网络编程v4pro--实现聊天室文件传输功能
java·服务器·网络·计算机网络
程序员黑豆6 小时前
Windows 系统 Java 环境变量配置全攻略:解决“不是内部或外部命令”
java·前端·ai编程
命运之光6 小时前
【C语言完整代码】就诊信息管理系统
java·c语言·开发语言
marvelyu7 小时前
每天10分钟学会OceanBase系列(Day 20):跨机房容灾实战——构建多数据中心高可用架构
java·大数据·数据库
AI人工智能+电脑小能手8 小时前
大白话说Java设计模式-04-工厂方法模式(业务实战篇)
java·设计模式·工厂方法模式·架构设计·代码解耦
BUG指挥官8 小时前
Sa-Token和Spring Security对比
java·后端·spring
小当家.1058 小时前
深入理解 ReAct Agent:从原理到 Java 实战
java·react.js·agent·react·架构设计·agent设计
geminigoth8 小时前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring
Hammer_Hans8 小时前
DFT笔记98
java·开发语言·数据库
古法安卓9 小时前
Android-DeviceStorageMonitorService 流程分析
java·面试·android studio