一、什么是IOC?
IOC(Inversion of Control,控制反转) 是Spring框架的基石,其核心在于将对象的创建、依赖注入和生命周期管理权交给容器。传统开发中,对象间的强耦合关系会导致“牵一发而动全身”的问题,而IOC通过工厂模式+反射机制实现了彻底的解耦。例如:
// 传统方式:类A直接依赖类B
class A {
B b = new B();
}
IOC的优势:
-
解耦:通过Spring容器统一管理对象生命周期,避免类之间的直接依赖。
-
灵活性:修改依赖关系时无需改动源码,只需调整配置文件或注解。
二、IOC程序的入门
1.创建java工程,导入坐标依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
2.编写接口和实现类,编写具体的实现方法
package com.qcby.service;
public interface UserService {
public void hello();
}
package com.qcby.service;
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("Hello IOC!!");
}
}
3.编写 Spring 核心的配置文件,在 src 目录下创建 applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--IOC 管理 bean-->
<bean id="userService" class="com.qcbyjy.service.UserServiceImpl"/>
</beans>
4.编写测试方法。
package com.qcbyjy.test;
import com.qcbyjy.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo1 {
@Test
public void run1(){
// 使用 Spring 的工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类:
UserService userService = (UserService) applicationContext.getBean("userService");
userService.hello();
}
}
三、依赖注入(Dependency Injection)DI
依赖注入:在 Spring 框架负责创建 Bean 对象时,动态的将依赖对象注入到 Bean 组件中
(1)属性的 set 方法注入值
编写属性,提供该属性对应的 set 方法,编写配置文件完成属性值的注入
package com.qcby.service;
import com.qcbyjy.dao.OrderDao;
public class OrderServiceImpl implements OrderService {
// 编写成员属性,一定需要提供该属性的 set 方法
private OrderDao orderDao;
// IOC容器底层通过属性的set方法注入值
public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
// 消息
private String msg;
// 年龄
private int age;
public void setMsg(String msg) {
this.msg = msg;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void saveOrder() {
System.out.println("业务层:保存订单..."+msg+" - "+age);
// 调用
orderDao.saveOrder();
}
}
package com.qcby.dao;
public class OrderDaoImpl implements OrderDao {
@Override
public void saveOrder() {
System.out.println("持久层:保存订单...");
}
}
<!--DI:依赖注入-->
<bean id="os" class="com.qcbyjy.service.OrderServiceImpl">
<property name="orderDao" ref="od" />
<property name="msg" value="你好" />
<property name="age" value="30" />
</bean>
<bean id="od" class="com.qcbyjy.dao.OrderDaoImpl"></bean>
(2)属性构造方法方式注入值
对于类成员变量,构造函数注入。
package com.qcbyjy.demo2;
public class Car {
// 名称
private String cname;
// 金额
private Double money;
public Car(String cname, Double money) {
this.cname = cname;
this.money = money;
}
@Override
public String toString() {
return "Car{" +"cname='" + cname + '\'' +", money=" + money +'}';
}
}
<bean id="car" class="com.qcbyjy.demo2.Car">
<constructor-arg name="cname" value="大奔" />
<constructor-arg name="money" value="400000" />
</bean>
(3)数组,集合(List,Set,Map),Properties等的注入
package com.qcbyjy.demo3;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CollectionBean {
// 数组
private String [] strs;
public void setStrs(String[] strs) {
this.strs = strs;
}
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
private Map<String,String> map;
public void setMap(Map<String, String> map) {
this.map = map;
}
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;}
@Override
public String toString() {
return "CollectionBean{" +"strs=" + Arrays.toString(strs) +",
list=" + list +", map=" + map +", properties=" + properties +'}';
}
}
<!--给集合属性注入值-->
<bean id="collectionBean" class="com.qcbyjy.demo3.CollectionBean">
<property name="strs">
<array>
<value>美美</value>
<value>小凤</value>
</array>
</property>
<property name="list">
<list>
<value>熊大</value>
<value>熊二</value>
</list>
</property>
<property name="map">
<map>
<entry key="aaa" value="老王"/>
<entry key="bbb" value="小王"/>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
多配置文件的加载方式
//1.主配置文件中包含其他的配置文件:
<import resource="applicationContext2.xml"/>
//2.工厂创建的时候直接加载多个配置文件:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml","applicationContext2.xml");
四、IOC 注解的方式
1. 常用注解
-
@Component:通用组件标记。
-
@Controller:表现层组件。
-
@Service:业务层组件。
-
@Repository:持久层组件。
2. 使用步骤
(1) 开启注解扫描
<context:component-scan base-package="com.qcby"/>
(2) 定义Bean
package com.qcbyjy.demo2;
import org.springframework.stereotype.Component;
//在需要管理的类上添加@Component 注解,代替<beanid="us"class="com.qcbyjy.demo2.UserServiceImpl" />
@Component(value = "us")
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("Hello IOC 注解...");
}
}
(3) 属性注入
依赖注入常用注解:
-
@Value:注入基本类型值。
-
@Autowired:按类型自动装配。
-
@Qualifier:按名称装配,需与@Autowired配合。
-
@Resource Java 提供的注解,也被支持。使用 name 属性,按名称注入
对象生命周期(作用范围)注解:
-
@Scope 生命周期注解,取值 singleton(默认值,单实例)和 prototype(多例)
初始化方法和销毁方法注解(了解):
- @PostConstruct 相当于 init-method
- @PreDestroy 相当于 destroy-method
@Service
public class UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Value("${jdbc.url}")
private String jdbcUrl;
@PostConstruct
public void init(){
System.out.println("进行初始化操作");
}
@PreDestroy
public void des(){
System.out.println("执行销毁操作");
}
}
六、纯注解配置(Spring Boot风格)
1. 核心注解
-
@Configuration:标记类为配置类。
-
@ComponentScan:指定扫描包路径。
2. 编写配置类,替换掉 applicationContext.xml 配置文件
@Configuration
@ComponentScan("com.qcby")
public class SpringConfig {
@Bean
public DataSource dataSource() {
return new DruidDataSource();
}
}
3. 测试代码
public class Test {
@Test
public void run1(){
// 创建工厂,加载配置类
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
// 获取到对象
Order order = (Order) ac.getBean("order");
System.out.println(order);
}
七、总结
-
IOC核心价值:通过解耦提升代码可维护性和扩展性。
-
XML vs 注解:
-
XML:集中管理配置,适合大型项目。
-
注解:简洁高效,适合快速开发。
-
-
适用场景:微服务架构下推荐纯注解方式,传统项目可混合使用。
掌握Spring IOC是Java开发的核心技能,合理运用能显著提升代码质量!

2174

被折叠的 条评论
为什么被折叠?



