Skip to content

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

特性BeanFactoryApplicationContext
初始化延迟加载预加载
功能基础功能更强大(事件、国际化等)
常用实现-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原型,每次获取创建新实例
requestHTTP 请求(需要 Web 环境)
sessionHTTP 会话(需要 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 生命周期⭐⭐⭐⭐⭐⭐⭐⭐
自动装配⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
配置方式⭐⭐⭐⭐⭐⭐⭐

⚠️ 易错点提醒

  1. 构造器注入是 Spring 团队推荐的方式
  2. 字段注入(@Autowired private xxx)不推荐,难以测试
  3. 多实现时记得用 @Primary 指定默认实现
  4. @Repository 在持久层还有异常转换功能
  5. Bean 懒加载 @Lazy 在第一次使用时才初始化