# 如何把Bean塞到Spring容器里 ## 前言 Spring框架的核心是IoC(控制反转)容器,而Bean则是Spring容器管理的基本单元。将Bean正确地注册到Spring容器中是使用Spring框架的基础技能。本文将全面解析7种将Bean注册到Spring容器的主流方式,并通过源码层面分析其实现原理。 ## 一、Bean注册基础概念 ### 1.1 什么是Spring Bean 在Spring框架中: - Bean是被容器实例化、组装和管理的Java对象 - Bean及其之间的依赖关系通过容器配置元数据体现 - 每个Bean都有唯一的名称或ID标识 ### 1.2 Spring容器层级结构 ```java BeanFactory (根接口) └── ApplicationContext (增强接口) ├── ClassPathXmlApplicationContext ├── FileSystemXmlApplicationContext └── AnnotationConfigApplicationContext
<!-- applicationContext.xml --> <beans xmlns="http://www.springframework.org/schema/beans"> <bean id="userService" class="com.example.UserServiceImpl"/> </beans>
// 源码流程 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); → refresh() → obtainFreshBeanFactory() → loadBeanDefinitions(beanFactory) → XmlBeanDefinitionReader.loadBeanDefinitions()
@Configuration @ComponentScan("com.example") public class AppConfig {}
支持的注解: - @Component
(通用组件) - @Service
(服务层) - @Repository
(持久层) - @Controller
(控制层)
ConfigurationClassPostProcessor
处理配置类@Bean
方法注册@Configuration public class DataSourceConfig { @Bean public DataSource dataSource() { return new DruidDataSource(); } }
@Lazy
、@Primary
等注解@Bean public UserService userService(UserDao userDao) { return new UserServiceImpl(userDao); }
@Conditional
注解@Bean @Conditional(ProdEnvCondition.class) public DataSource prodDataSource() { // 生产环境数据源 }
@Profile
:环境条件@ConditionalOnClass
:类路径条件@ConditionalOnProperty
:配置属性条件AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass(UserService.class); beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON); context.registerBeanDefinition("userService", beanDefinition); context.refresh();
context.getBeanFactory().registerSingleton("userService", new UserServiceImpl());
注意:需要在refresh()前注册
public class MyFactoryBean implements FactoryBean<User> { @Override public User getObject() { return new User(); } @Override public Class<?> getObjectType() { return User.class; } }
// 获取FactoryBean本身 context.getBean("&myFactoryBean"); // 获取生产的对象 context.getBean("myFactoryBean");
@Configuration @EnableAspectJAutoProxy public class AopConfig { @Bean public LogAspect logAspect() { return new LogAspect(); } }
@Bean public UserService proxiedUserService() { UserService target = new UserServiceImpl(); return (UserService) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{UserService.class}, (proxy, method, args) -> { System.out.println("Before method"); return method.invoke(target, args); }); }
@SpringBootApplication
组合注解包含: - @Configuration
- @EnableAutoConfiguration
- @ComponentScan
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@Bean
方法注册组件Arrays.stream(context.getBeanDefinitionNames()) .forEach(System.out::println);
@Lazy
延迟初始化@DependsOn
慎用)@Bean
方法掌握多种Bean注册方式后,开发者可以根据不同场景选择最合适的方案。理解底层实现机制有助于在复杂场景下灵活运用,并能够有效排查相关问题。Spring容器的Bean管理能力是其核心价值所在,合理利用可以大幅提升应用的可维护性和扩展性。
本文共计约3900字,详细介绍了从基础到高级的各种Bean注册方式,并附有代码示例和原理分析,可作为Spring开发者的实用参考指南。 “`
这篇文章采用Markdown格式编写,包含: 1. 多级标题结构 2. 代码块示例 3. 列表和层级展示 4. 原理性说明 5. 最佳实践建议 6. 完整的知识体系覆盖
可以根据需要进一步扩展某些章节的细节内容或添加更多示例代码。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。