Sping中获取bean的方式总结-笔记
1. 获取spring管理bean的方式
1.1 通过@Autowired
依赖注入
通过字段、构造函数或 setter 方法自动注入Bean,是Spring最常用的方式。
@Service
public class MyBeanConsumer {// 字段注入@Autowiredprivate MyService myService;
}@Service
public class MyBeanConsumer {private MyService myService;// 构造函数注入@Autowiredpublic MyBeanConsumer(MyService myService) {this.myService = myService;}
}@Service
public class MyBeanConsumer {private MyService myService;// Setter注入@Autowiredpublic void setMyService(MyService myService) {this.myService = myService;}
}
1.2. 通过@Resource
依赖注入
使用Java EE标准的@Resource
注解,按名称注入(默认按字段名匹配Bean名称)。
@Service
public class MyBeanConsumer {// 按字段名"myService"匹配Bean名称@Resourceprivate MyService myService;// 显式指定Bean名称(如Bean名为"anotherService")@Resource(name = "anotherService")private MyService anotherService;
}
1.3 通过ApplicationContext
的getBean()
方法
这是直接通过ApplicationContext
上下文获取Bean的方式,适用于需要动态或按名称获取Bean的场景。
// 在某个组件或测试类中注入ApplicationContext
@Service
public class MyBeanConsumer {@Autowiredprivate ApplicationContext context;public void doSomething() {// 按类型获取Bean(若存在多个同类型Bean需指定名称)MyService myService = context.getBean(MyService.class);// 按名称+class获取Bean(需指定Bean名称)MyService namedService = context.getBean("myServiceBean", MyService.class);// 按名称获取MyService myService = (MyService)context.getBean("myServiceBean");}
}
1.4. 通过ApplicationContextAware
接口
通过实现ApplicationContextAware
接口,保存ApplicationContext
的引用,从而全局获取Bean。
@Component //需要使用@Component,让spring能够扫描到该工具类
public class SpringContextUtil implements ApplicationContextAware {private static ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {//Spring项目启动过程中,会执行ApplicationContextAware接口实现类的setApplicationContext方法,自动注入applicationContextcontext = applicationContext;}// 静态方法供其他类调用// 通过class获取Beanpublic static <T> T getBean(Class<T> beanClass) {return context.getBean(beanClass);}//通过beanName+Clazz返回指定的Beanpublic static <T> T getBean(String beanName, Class<T> clazz) {return getApplicationContext().getBean(beanName, clazz);}//通过beanName获取 Beanpublic static Object getBean(String beanName){return context.getBean(beanName);}
}// 在其他类中使用
public class AnotherClass {public void someMethod() {MyService service = SpringContextUtil.getBean(MyService.class);}
}
1.5. 通过BeanFactory
的getBean()
方法
BeanFactory
是Spring的核心接口,ApplicationContext
继承自它,功能类似。
@Service
public class MyBeanConsumer {@Autowiredprivate BeanFactory beanFactory;public void doSomething() {// 按类型获取Bean(若存在多个同类型Bean需指定名称)MyService myService = beanFactory.getBean(MyService.class);// 按名称+class获取Bean(需指定Bean名称)MyService namedService = beanFactory.getBean("myServiceBean", MyService.class);// 按名称获取MyService myService = (MyService)beanFactory.getBean("myServiceBean");}
}
2. 各种获取bean方式的对比
2.1 各方式的对比分析
方式 | 依赖注入方式 | 适用场景 | 侵入性 | 灵活性 | 可测试性 | 性能 |
---|---|---|---|---|---|---|
@Autowired | 自动注入(类型匹配) | 常规 Bean 注入,类型唯一时 | 低 | 中 | 高(依赖注入) | 高(启动时完成注入) |
@Resource | 自动注入(名称匹配) | 需明确指定 Bean 名称时 | 低 | 中 | 高 | 高 |
ApplicationContext.getBean() | 手动获取 | 动态获取 Bean(如条件判断) | 中(需持有上下文) | 高(动态选择) | 低(需模拟上下文) | 中(需查找 Bean) |
ApplicationContextAware | 手动获取 | 需全局访问 ApplicationContext | 高(全局耦合) | 高 | 低 | 中 |
BeanFactory.getBean() | 手动获取 | 底层 API 场景 | 中 | 高 | 低 | 中 |
2.2 关键对比说明
1. 自动注入 vs 手动获取
-
自动注入(
@Autowired
/@Resource
):- 优点:代码简洁,符合依赖注入原则,无需显式查找 Bean。
- 缺点:灵活性低,无法动态选择 Bean(如根据条件)。
- 最佳实践:优先使用,适合常规场景。
-
手动获取(
getBean()
/ApplicationContextAware
):- 优点:灵活,支持动态选择 Bean。
- 缺点:代码侵入性高,可能破坏依赖注入原则。
- 适用场景:必须动态选择 Bean(如多环境配置)或在非 Spring 管理的类中使用。
2. 类型匹配 vs 名称匹配
@Autowired
:按类型匹配,若存在多个同类型 Bean 需结合@Qualifier
指定名称。@Resource
:默认按名称匹配,更明确且跨框架兼容(如 JEE 环境)。
3. 性能与可测试性
- 自动注入:性能高,因为 Spring 启动时已完成依赖注入,测试时可通过 Mock 框架(如 Mockito)模拟依赖。
- 手动获取:可能需要额外的上下文模拟,测试复杂度较高。
4. 全局访问的陷阱
ApplicationContextAware
:- 优点:提供全局访问
ApplicationContext
的能力。 - 缺点:隐藏依赖,增加耦合,可能导致代码难以维护。
- 最佳实践:仅在必要时(如工具类)使用,并限制其范围。
- 优点:提供全局访问
2.3 推荐使用场景
场景 | 推荐方式 |
---|---|
常规 Bean 注入(类型唯一) | @Autowired 或 @Resource |
需要明确指定 Bean 名称时 | @Resource |
动态选择 Bean(如多环境配置) | ApplicationContext.getBean() |
需要全局访问 ApplicationContext | ApplicationContextAware |
非 Spring 管理的类中获取 Bean | ApplicationContext 传递 |
最佳实践总结
- 优先使用依赖注入(
@Autowired
/@Resource
),遵循“依赖注入优于查找”的原则。 - 避免滥用
getBean()
:仅在必须动态选择或非 Spring 管理的场景使用。 - 谨慎使用全局上下文(如
ApplicationContextAware
),防止过度耦合。 - 明确 Bean 唯一性:若存在多个同类型 Bean,使用
@Qualifier
或@Resource
显式指定名称。
3. 相关文档
Spring中生成Bean的方式总结-笔记-CSDN博客