IOC 注解方式详解
目标:掌握 Spring 中使用 注解(Annotation) 实现 IOC(控制反转)与 DI(依赖注入)的方法。
1️⃣ IOC 注解方式快速入门
1.1 依赖环境
与 XML 配置方式相同,只是 Bean 的定义改用注解完成。
1.2 编写接口与实现类
接口:
package com.qcbyjy.demo2;public interface UserService {void hello();
}
实现类:
package com.qcbyjy.demo2;import org.springframework.stereotype.Component;/*** 等价于:* <bean id="us" class="com.qcbyjy.demo2.UserServiceImpl" />*/
@Component(value = "us")
public class UserServiceImpl implements UserService {@Overridepublic void hello() {System.out.println("Hello IOC注解...");}
}
🔹
@Component作用:让 Spring 自动管理这个类为 Bean。
如果不写value,默认使用类名首字母小写作为 ID(例如userServiceImpl)。
2️⃣ 开启注解扫描
在 applicationContext_anno.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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启注解扫描 --><context:component-scan base-package="com.qcbyjy" /></beans>
3️⃣ 测试 IOC 注解方式
package com.qcbyjy.test;import com.qcbyjy.demo2.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Demo2 {@Testpublic void run1() {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_anno.xml");UserService userService = (UserService) ac.getBean("us");userService.hello();}
}
运行结果:
Hello IOC注解...
4️⃣ 常用注解分类总结
(1)Bean 管理注解(创建 Bean)
| 注解 | 作用层次 | 说明 |
|---|---|---|
| @Component | 通用组件类 | 最基础的注解 |
| @Controller | 表现层(Web 层) | 控制器组件 |
| @Service | 业务逻辑层 | Service 组件 |
| @Repository | 持久层 | Dao 组件 |
(2)依赖注入注解(注入 Bean)
| 注解 | 用途 |
|---|---|
| @Value | 注入普通类型属性(String、int、double 等) |
| @Autowired | 按类型自动装配(引用类型) |
| @Qualifier | 和 @Autowired 一起使用,按名称注入 |
| @Resource | 按名称注入(Java 原生注解) |
(3)Bean 作用域注解
| 注解 | 说明 |
|---|---|
| @Scope("singleton") | 单例(默认) |
| @Scope("prototype") | 多例,每次获取新对象 |
(4)生命周期注解
| 注解 | 对应 XML 属性 | 说明 |
|---|---|---|
| @PostConstruct | init-method | 初始化方法 |
| @PreDestroy | destroy-method | 销毁方法 |
单例 Bean 的销毁由 容器关闭 控制,多例 Bean 的销毁由 GC(垃圾回收) 控制。
5️⃣ 示例:综合使用注解
Car.java
package com.qcbyjy.demo3;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;@Component(value = "c")
// @Scope("prototype") // 可切换作用域
public class Car {@Value("大奔2")private String cname;@Value("400000")private Double money;@Autowiredprivate Person person;@PostConstructpublic void init() {System.out.println("Car对象初始化完成...");}@Overridepublic String toString() {return "Car{" +"cname='" + cname + '\'' +", money=" + money +", person=" + person +'}';}
}
Person.java
package com.qcbyjy.demo3;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component(value = "person")
public class Person {@Value("张三")private String pname;@Overridepublic String toString() {return "Person{" + "pname='" + pname + '\'' + '}';}
}
测试类:
package com.qcbyjy.test;import com.qcbyjy.demo3.Car;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Demo3 {@Testpublic void run1() {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_anno.xml");Car car = (Car) ac.getBean("c");System.out.println(car);}
}
运行结果:
Car对象初始化完成...
Car{cname='大奔2', money=400000.0, person=Person{pname='张三'}}
6️⃣ IOC 纯注解方式(无 XML)
在微服务开发中,Spring Boot 就是基于这种“纯注解配置”的方式。
6.1 编写实体类
package com.qcbyjy.demo4;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class Order {@Value("北京")private String address;@Overridepublic String toString() {return "Order{" + "address='" + address + '\'' + '}';}
}
6.2 编写配置类(替代 XML)
package com.qcbyjy.demo4;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration // 声明当前类为配置类
@ComponentScan("com.qcbyjy.demo4") // 扫描包
public class SpringConfig {
}
6.3 编写测试类
package com.qcbyjy.test;import com.qcbyjy.demo4.Order;
import com.qcbyjy.demo4.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Demo4 {@Testpublic void run1() {ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);Order order = (Order) ac.getBean("order");System.out.println(order);}
}
运行结果:
Order{address='北京'}
7️⃣ 多配置类与 @Import、@Bean
7.1 多配置类拆分与引入
SpringConfig2.java
package com.qcbyjy.demo4;import org.springframework.context.annotation.Configuration;@Configuration
public class SpringConfig2 {
}
SpringConfig.java
package com.qcbyjy.demo4;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Configuration
@ComponentScan("com.qcbyjy.demo4")
@Import(SpringConfig2.class) // 引入另一个配置类
public class SpringConfig {
}
7.2 使用 @Bean 注册第三方 Bean
package com.qcbyjy.demo4;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;import javax.sql.DataSource;@Configuration
@ComponentScan("com.qcbyjy.demo4")
@Import(SpringConfig2.class)
public class SpringConfig {/*** 创建连接池对象并交给 Spring 容器管理* 等价于 XML:** <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">* <property name="driverClassName" value="com.mysql.jdbc.Driver"/>* <property name="url" value="jdbc:mysql:///spring_db"/>* <property name="username" value="root"/>* <property name="password" value="root"/>* </bean>*/@Bean(name = "dataSource")public DataSource createDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///spring_db");dataSource.setUsername("root");dataSource.setPassword("root");return dataSource;}
}
✅ 总结
| 注解 | 作用 |
|---|---|
| @Component / @Controller / @Service / @Repository | Bean 定义 |
| @Value / @Autowired / @Qualifier / @Resource | 属性注入 |
| @Scope / @PostConstruct / @PreDestroy | 生命周期管理 |
| @Configuration / @ComponentScan / @Import / @Bean | 纯注解配置 |
🌱 小结:
从 XML 到注解再到纯注解配置,是 Spring 容器发展的必然趋势。
掌握注解式开发,是通向 Spring Boot 与微服务架构的基础!
