依赖注入(Dependency Injection)是Spring框架的核心特性,它实现了对象之间的解耦。本文将详细介绍三种常用的依赖注入方式,并结合实际代码演示其应用。
1. Setter方法注入(设置值注入)
原理:通过调用Bean的setter方法注入属性值
特点:灵活,可选择性注入部分属性
XML配置:
Java代码:
@Test
public void run1(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
User user1 = (User) context.getBean("user");
System.out.println(user1.toString());
// 输出: User{username='张三', age=18, gender='男'}
}
测试代码:
@Test
public void run1(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
User user1 = (User) context.getBean("user");
System.out.println(user1.toString());
// 输出: User{username='张三', age=18, gender='男'}
}
优势:
可单独注入特定属性
支持重新注入(属性可变)
与构造器注入互补
2. 构造器注入
原理:通过构造函数参数注入属性值
特点:创建对象时即完成初始化,属性不可变
XML配置:
Java代码:
设置完有参的构造器一定要将无参的构造器一并写出:因为默认使用的是无参构造器的方法,一旦设置有参不设置无参找不到就会报错
public class User {
// 带参构造器
public User(String username, Integer age, String gender) {
this.username = username;
this.age = age;
this.gender = gender;
}
}
测试代码:
@Test
public void run2(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
User user2 = (User) context.getBean("user2");
System.out.println(user2.toString());
// 输出: User{username='李四', age=19, gender='男'}
}
优势:
确保完全初始化的对象
适合必需依赖项
线程安全(属性不可变)
3. P命名空间注入
原理:XML简写语法,本质是setter注入的快捷方式
特点:配置简洁,支持对象引用注入
XML配置:
xmlns:p="http://www.springframework.org/schema/p"
p:username="花花" p:age="20" p:gender="女" p:hajimi-ref="user2"/> Java代码: public class User { // 对象引用属性 private User hajimi; public void setHajimi(User hajimi) { this.hajimi = hajimi; } } 测试代码: @Test public void run3(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); User user3 = (User) context.getBean("user3"); System.out.println(user3.toString()); // 获取注入的对象引用 User hajimiUser = user3.getHajimi(); System.out.println(hajimiUser.toString()); /* 输出: User{username='花花', age=20, gender='女'} User{username='李四', age=19, gender='男'} */ } 优势: 配置简洁明了 支持基本类型和对象引用(-ref)注入 减少XML配置量 三种注入方式对比 特性Setter注入构造器注入P命名空间注入配置语法 对象引用注入详解 在Spring中,可以注入其他Bean作为属性,形成对象关联: Java: public class User { private User hajimi; // 引用其他User对象 } XML配置:
p:hajimi-ref="user2"/> 对象关系图: user3 ────┬──▶ username: "花花" ├──▶ age: 20 └──▶ hajimi ────┬──▶ username: "李四" (user2) ├──▶ age: 19 └──▶ gender: "男" 最佳实践建议 首选构造器注入(强制依赖) // 确保必需依赖项在构造时提供 public class OrderService { private final PaymentService paymentService; public OrderService(PaymentService paymentService) { this.paymentService = paymentService; } } Setter注入用于可选依赖 // 可选日志依赖 public class ProductService { private Logger logger; public void setLogger(Logger logger) { this.logger = logger; } } P命名空间简化配置 p:jdbcUrl="jdbc:mysql://localhost/db" p:username="root" p:password="secret"/> 避免的常见错误 缺少setter方法(setter注入) 构造器参数不匹配(构造器注入) 对象引用未定义(p:属性名-ref) 循环依赖(A依赖B,B又依赖A) 完整项目结构 src ├── main │ ├── java │ │ ├── com.qcby │ │ │ └── DI.java # 测试类 │ │ └── com.qcby.entity │ │ └── User.java # 实体类 │ └── resources │ └── spring.xml # Spring配置 通过合理运用这三种依赖注入方式,可以构建松耦合、易测试的应用程序。Spring的DI机制让对象协作变得简单而优雅。