通过注解实现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;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", address=" + address +'}';}@Value("李华")private String name;@Resourceprivate 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;}@Overridepublic 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"));}
}
结果:
补充知识
要通过注解实现 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
标记。
以你之前的 Address
和 Student
为例:
// 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 类型的 Beanprivate 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 类型的 Beanprivate Address address;// 其他属性略...
}
2. 构造器注入(Spring 推荐,更利于依赖检查)
@Component
public class Student {private final Address address;private Integer id;private String name;private Integer age;@Autowired // 构造器上标记,Spring 会自动传入 Address Beanpublic 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
有子类 HomeAddress
和 SchoolAddress
),需结合 @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" 的 Beanprivate Address address;// ...
}
七、注解 vs XML:优缺点对比
方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
注解 | 简洁、无 XML 冗余、开发效率高 | 配置与代码耦合(需修改类) | 大多数场景,尤其是 Spring Boot 项目 |
XML | 配置与代码分离、便于统一管理 | 冗余代码多、维护成本高 | 需频繁修改配置(如环境切换)、旧项目兼容 |
而且注解一次只可以实现一个类
通过注解实现 IOC 后,Spring 会自动扫描、创建 Bean 并完成依赖注入,大幅简化了配置流程。如果你的项目是 Spring Boot,只需在主类上加 @SpringBootApplication
(内部包含 @ComponentScan
),即可零配置实现 IOC。