03-spirngIOC02-通过注解实现IOC

通过注解实现IOC


实现实体类

package com.zhongge.entity;

import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @ClassName User
 * @Description TODO
 * @Author zhongge
 * @Version 1.0
 */
@Component("user01")
public class User {
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", address=" + address +
                '}';
    }

    @Value("李华")
    private String name;
    @Resource
    private Address address;
}

package com.zhongge.entity;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @ClassName Address
 * @Description TODO
 * @Author zhongge
 * @Version 1.0
 */
@Component
public class Address {
    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    @Override
    public String toString() {
        return "Address{" +
                "loc='" + loc + '\'' +
                '}';
    }

    @Value("毕节")
    private String loc;

    public Address(String loc) {
        this.loc = loc;
    }


    public Address() {
    }
}

测试结果


package com.zhongge.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @ClassName Main
 * @Description TODO
 * @Author zhongge
 * @Version 1.0
 */
public class Main {
    public static void main(String[] args) {
        //通过注解获取IOC容器
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.zhongge.entity");
        //通过IOC容器获取对象
        System.out.println(applicationContext.getBean("user01"));
    }
}

结果:
image


补充知识

要通过注解实现 Spring IOC,需遵循以下核心步骤,结合注解扫描、Bean 标记和依赖注入来完成容器管理:

一、核心注解说明

Spring 提供了一系列注解来替代 XML 配置,实现“零 XML”式 IOC:

注解 作用
@Component 通用组件注解,标记类为 Spring 管理的 Bean(可用于任何层)。
@Service 语义化注解,专用于业务逻辑层(Service 层),功能同 @Component
@Repository 语义化注解,专用于数据访问层(DAO 层),功能同 @Component
@Controller 语义化注解,专用于控制层(如 SpringMVC 的 Controller)。
@Autowired 自动依赖注入,按类型匹配 Bean(可结合 @Qualifier 按名称匹配)。

二、步骤 1:开启注解扫描(替代 XML 的 <context:component-scan>

在 Spring 配置类中用 @ComponentScan 指定需要扫描的包(若用 XML 则需配置 <context:component-scan>)。

方式 1:纯注解配置(推荐 Spring Boot)

@Configuration  // 标记为 Spring 配置类
@ComponentScan(basePackages = "com.zhongge")  // 扫描指定包及其子包下的注解
public class AppConfig {
    // 无需额外配置,注解扫描由 @ComponentScan 完成
}

方式 2:XML 配置(兼容传统 Spring)

若仍需保留 XML,在 applicationContext.xml 中添加:

<!-- 开启注解扫描,Spring 会自动处理 @Component/@Service 等注解 -->
<context:component-scan base-package="com.zhongge"/>

三、步骤 2:用注解标记 Bean(替代 XML 的 <bean> 标签)

将需要由 Spring 管理的类用 @Component/@Service/@Repository/@Controller 标记。

以你之前的 AddressStudent 为例:

// com.zhongge.entity.Address
@Component  // 标记为 Spring Bean(也可用 @Service/@Repository 等,语义化可选)
public class Address {
    private String loc;

    // Getter/Setter/toString 略
}

// com.zhongge.entity.Student
@Component
public class Student {
    @Autowired  // 自动注入 Address 类型的 Bean
    private Address address;
    private Integer id;
    private String name;
    private Integer age;

    // 构造器/Setter/toString 略
}

四、步骤 3:依赖注入(用 @Autowired 替代 XML 的 <property>/<constructor-arg>

@Autowired 支持字段注入构造器注入Setter 注入三种方式,推荐构造器注入(更符合 Spring 官方推荐)。

1. 字段注入(最简单,直接在属性上标记)

@Component
public class Student {
    @Autowired  // 直接注入 Address 类型的 Bean
    private Address address;
    // 其他属性略...
}

2. 构造器注入(Spring 推荐,更利于依赖检查)

@Component
public class Student {
    private final Address address;
    private Integer id;
    private String name;
    private Integer age;

    @Autowired  // 构造器上标记,Spring 会自动传入 Address Bean
    public Student(Address address) {
        this.address = address;
    }

    // Setter/toString 略...
}

3. Setter 注入(需提供 Setter 方法)

@Component
public class Student {
    private Address address;
    // 其他属性略...

    @Autowired  // 在 Setter 方法上标记
    public void setAddress(Address address) {
        this.address = address;
    }
}

五、测试注解版 IOC(编写 Main 类)

public class Main {
    public static void main(String[] args) {
        // 加载注解配置类(或 XML 配置)
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 或加载 XML:new ClassPathXmlApplicationContext("applicationContext.xml");

        Student student = context.getBean(Student.class);
        System.out.println(student); // 应输出包含 Address 的 Student 对象
    }
}

六、进阶:多 Bean 冲突时的处理

若同一接口有多个实现类(如 Address 有子类 HomeAddressSchoolAddress),需结合 @Qualifier 按名称注入:

// 多个 Address 实现类
@Component("homeAddress")
public class HomeAddress extends Address { ... }

@Component("schoolAddress")
public class SchoolAddress extends Address { ... }

// Student 中指定注入名称
@Component
public class Student {
    @Autowired
    @Qualifier("homeAddress") // 明确注入名称为 "homeAddress" 的 Bean
    private Address address;
    // ...
}

七、注解 vs XML:优缺点对比

方式 优点 缺点 适用场景
注解 简洁、无 XML 冗余、开发效率高 配置与代码耦合(需修改类) 大多数场景,尤其是 Spring Boot 项目
XML 配置与代码分离、便于统一管理 冗余代码多、维护成本高 需频繁修改配置(如环境切换)、旧项目兼容

而且注解一次只可以实现一个类
通过注解实现 IOC 后,Spring 会自动扫描、创建 Bean 并完成依赖注入,大幅简化了配置流程。如果你的项目是 Spring Boot,只需在主类上加 @SpringBootApplication(内部包含 @ComponentScan),即可零配置实现 IOC。

posted on 2025-10-04 23:42  笨忠  阅读(8)  评论(0)    收藏  举报