Appearance
Spring Core - IoC 与 DI
Spring 简介
Spring 是最流行的 Java 企业级开发框架,核心是 IoC 容器 和 AOP。
┌─────────────────────────────────────────────────────────────────┐
│ Spring 核心模块 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Spring Framework │
│ ┌─────────────┬─────────────┬─────────────┐ │
│ │ Spring Core │ Spring │ Spring │ │
│ │ (IoC/DI) │ AOP │ TX │ │
│ ├─────────────┼─────────────┼─────────────┤ │
│ │ Spring │ Spring │ Spring │ │
│ │ Web MVC │ Web │ WebSocket │ │
│ └─────────────┴─────────────┴─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘IoC 容器
什么是 IoC?
控制反转(Inversion of Control):对象的创建和管理由容器负责,而不是由应用代码直接管理。
┌─────────────────────────────────────────────────────────────────┐
│ 传统方式 vs IoC │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ❌ 传统方式:应用代码直接创建对象 │
│ ───────────────────── │
│ UserService service = new UserService(); │
│ │
│ ✅ IoC 方式:容器创建对象,应用代码使用 │
│ ───────────────────── │
│ ApplicationContext ctx = ...; │
│ UserService service = ctx.getBean(UserService.class); │
│ │
└─────────────────────────────────────────────────────────────────┘BeanFactory vs ApplicationContext
| 特性 | BeanFactory | ApplicationContext |
|---|---|---|
| 初始化 | 延迟加载 | 预加载 |
| 功能 | 基础功能 | 更强大(事件、国际化等) |
| 常用实现 | - | ClassPathXmlApplicationContext |
| AnnotationConfigApplicationContext | ||
| FileSystemXmlApplicationContext |
DI 依赖注入
三种注入方式
java
// 1. 构造器注入(推荐)
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired // 如果只有一个构造器,@Autowired 可省略
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
// 2. Setter 注入
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
// 3. 字段注入(不推荐)
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}@Component 家族
| 注解 | 说明 | 应用场景 |
|---|---|---|
| @Component | 通用组件 | 不属于以下类别 |
| @Service | 服务层组件 | 业务逻辑层 |
| @Repository | 持久层组件 | 数据访问层(还有异常转换) |
| @Controller | 控制层组件 | Web 层 |
| @Configuration | 配置类 | 配置类 |
java
// DAO 层
@Repository
public class UserRepository {
public User findById(Long id) { ... }
}
// Service 层
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUser(Long id) {
return userRepository.findById(id);
}
}
// Controller 层
@Controller
public class UserController {
@Autowired
private UserService userService;
}Bean 作用域
java
@Component
@Scope("singleton") // 默认作用域
public class MyBean { }
@Scope("prototype") // 每次获取新实例
@Scope("request") // HTTP 请求(Web)
@Scope("session") // HTTP 会话(Web)| 作用域 | 说明 |
|---|---|
| singleton | 单例(默认),容器中只有一个实例 |
| prototype | 原型,每次获取创建新实例 |
| request | HTTP 请求(需要 Web 环境) |
| session | HTTP 会话(需要 Web 环境) |
Bean 生命周期
┌─────────────────────────────────────────────────────────────────┐
│ Bean 生命周期 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 实例化 → 属性赋值 → BeanNameAware → BeanFactoryAware │
│ ↓ │
│ ApplicationContextAware → BeanPostProcessor.before │
│ ↓ │
│ 初始化方法(@PostConstruct / InitializingBean) │
│ ↓ │
│ BeanPostProcessor.after → 使用中 │
│ ↓ │
│ 销毁方法(@PreDestroy / DisposableBean) │
│ │
└─────────────────────────────────────────────────────────────────┘java
@Component
public class MyBean implements InitializingBean, DisposableBean {
@PostConstruct
public void init() {
System.out.println("Bean 初始化后执行");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean 初始化");
}
@PreDestroy
public void cleanup() {
System.out.println("Bean 销毁前执行");
}
@Override
public void destroy() {
System.out.println("DisposableBean 销毁");
}
}自动装配
@Autowired 详解
java
@Service
public class UserService {
// 1. byType(默认)
@Autowired
private UserRepository userRepository;
// 2. byName - 使用 @Qualifier
@Autowired
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;
// 3. 多个同类型 Bean
@Autowired
private List<SomeInterface> implementations;
// 4. 可选注入
@Autowired(required = false)
private Optional<SomeService> someService;
}@Primary 与 @Qualifier
java
// 多个实现类时,指定默认选择
@Repository
@Primary
public class PrimaryRepositoryImpl implements UserRepository { }
@Repository
public class SecondaryRepositoryImpl implements UserRepository { }
// 使用
@Service
public class UserService {
@Autowired
private UserRepository userRepository; // 自动选择 Primary
}配置方式
XML 配置(传统方式)
xml
<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">
<bean id="userService" class="com.example.UserService">
<property name="userRepository" ref="userRepository"/>
</bean>
<bean id="userRepository" class="com.example.UserRepositoryImpl"/>
</beans>Java 配置(现代方式)
java
@Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new UserRepositoryImpl();
}
@Bean
public UserService userService() {
return new UserService(userRepository());
}
}组件扫描
java
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig { }
// 排除某些组件
@ComponentScan(
basePackages = "com.example",
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX,
pattern = "com\\.example\\.test\\..*")
)条件装配
java
// 当存在某个类时才注册
@ConditionalOnClass(Tomcat.class)
// 当存在某个属性时
@ConditionalOnProperty(prefix = "spring.datasource", name = "url")
// 当是 Web 环境时
@ConditionalOnWebApplication
// 自定义条件
@Conditional(MyCondition.class)
public class SomeBean { }外部配置
@Value 注入
java
@Component
public class MyComponent {
@Value("hello")
private String simpleValue;
@Value("${app.name}")
private String propertyValue;
@Value("${app.description:默认描述}")
private String defaultValue;
@Value("#{systemProperties['java.version']}")
private String systemValue;
}@ConfigurationProperties
java
// application.yml
// app:
// name: 我的应用
// port: 8080
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private int port;
// getters and setters
}总结
Spring Core 核心知识点:
| 知识点 | 面试频率 | 实战重要性 |
|---|---|---|
| IoC/DI 原理 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| @Component 家族 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Bean 作用域 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| Bean 生命周期 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 自动装配 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 配置方式 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
⚠️ 易错点提醒:
- 构造器注入是 Spring 团队推荐的方式
- 字段注入(@Autowired private xxx)不推荐,难以测试
- 多实现时记得用 @Primary 指定默认实现
- @Repository 在持久层还有异常转换功能
- Bean 懒加载 @Lazy 在第一次使用时才初始化