IoC(Inversion of Control)控制反转,将对象的创建和依赖关系的管理交给容器。
// 传统方式:自己创建依赖
public class UserService {
private UserDao userDao = new UserDaoImpl();
}
// IoC 方式:容器注入依赖
public class UserService {
@Autowired
private UserDao userDao;
}
@Service
public class UserService {
private final UserDao userDao;
@Autowired // Spring 4.3+ 可省略
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
@Service
public class UserService {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
}
| 方式 | 优点 | 缺点 |
|---|
| 构造器注入 | 不可变、完全初始化、便于测试 | 参数多时代码冗长 |
| Setter 注入 | 可选依赖、可重新注入 | 对象可能不完整 |
| 字段注入 | 简洁 | 不便于测试、隐藏依赖 |
| 作用域 | 说明 |
|---|
| singleton | 单例(默认),整个容器只有一个实例 |
| prototype | 原型,每次获取创建新实例 |
| request | 每个 HTTP 请求一个实例 |
| session | 每个 HTTP Session 一个实例 |
| application | 每个 ServletContext 一个实例 |
@Component
@Scope("prototype")
public class PrototypeBean {
}
@Component
public class MyBean implements InitializingBean, DisposableBean {
@PostConstruct
public void postConstruct() {
System.out.println("@PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean.afterPropertiesSet");
}
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy");
}
@Override
public void destroy() {
System.out.println("DisposableBean.destroy");
}
}
@Component
public class MyBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {
@Override
public void setBeanName(String name) {
System.out.println("Bean 名称: " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
System.out.println("BeanFactory: " + beanFactory);
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
System.out.println("ApplicationContext: " + ctx);
}
}
在 Bean 初始化前后进行处理。
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("初始化前: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("初始化后: " + beanName);
return bean; // 可以返回代理对象
}
}
在 Bean 定义加载后、实例化前修改 Bean 定义。
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
BeanDefinition bd = beanFactory.getBeanDefinition("myBean");
bd.setScope("prototype");
}
}
| 注解 | 说明 |
|---|
| @Component | 通用组件 |
| @Service | 业务层 |
| @Repository | 数据访问层 |
| @Controller | 控制层 |
// 按类型注入
@Autowired
private UserDao userDao;
// 按名称注入
@Autowired
@Qualifier("mysqlUserDao")
private UserDao userDao;
// JSR-250 按名称注入
@Resource(name = "mysqlUserDao")
private UserDao userDao;
// 注入值
@Value("${app.name}")
private String appName;
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService();
}
@Bean
@Conditional(OnPropertyCondition.class)
public DataSource dataSource() {
return new HikariDataSource();
}
}
@Service
public class A {
@Autowired
private B b;
}
@Service
public class B {
@Autowired
private A a;
}
| 缓存 | 说明 |
|---|
| singletonObjects | 一级缓存,完整的 Bean |
| earlySingletonObjects | 二级缓存,早期暴露的 Bean |
| singletonFactories | 三级缓存,Bean 工厂 |
- 构造器注入的循环依赖
- prototype 作用域的循环依赖
// 构造器注入循环依赖,启动失败
@Service
public class A {
public A(B b) {}
}
@Service
public class B {
public B(A a) {}
}
// 解决方案:使用 @Lazy
@Service
public class A {
public A(@Lazy B b) {}
}
| 特性 | BeanFactory | ApplicationContext |
|---|
| Bean 加载 | 延迟加载 | 预加载 |
| 国际化 | 不支持 | 支持 |
| 事件发布 | 不支持 | 支持 |
| AOP | 需要手动配置 | 自动配置 |
// BeanFactory
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
// ApplicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);