Springbean注册与获取方式自查
本文档整理 Spring Framework 中把 Bean 放进容器和从容器取出 Bean的常见方式每种方式均附可运行的代码示例。一、对照表格表 1注入到容器的方法把 Bean 放进去方法注解/方式典型使用场景示例组件扫描Component/Service/Repository/Controller自己编写的业务类、工具类Service public class UserService {}配置类 BeanBeanConfiguration第三方库DataSource、RestTemplate或需自定义初始化的 BeanBean public DataSource ds() { return new HikariDataSource(); }导入配置Import将其他配置类中的 Bean 一并注册Import({DbConfig.class, CacheConfig.class})编程式注册context.registerBean(...)动态注册很少用context.registerBean(myBean, MyClass.class, () - new MyClass());XML 配置bean id... class.../老项目遗留写法bean idds classcom.zaxxer.hikari.HikariDataSource/表 2从容器中取的方法把 Bean 拿出来用方法注解/方式典型使用场景示例字段注入Autowired最常见的注入方式但官方不推荐Autowired private UserRepository repo;构造器注入构造参数无需注解官方推荐依赖可见、易测试public UserService(UserRepository repo) { this.repo repo; }Setter 注入Autowired加在 setter 上可选依赖Autowired public void setRepo(UserRepository repo) { ... }按名称注入QualifierAutowired多个同类型 Bean 时按名称精确取出Qualifier(orderDb) Autowired DataSource ds;按名称注入Resource(namexxx)需明确指定 Bean 名称Java 原生注解Resource(namereportDb) private DataSource ds;首选 BeanPrimary不指定名称时默认注入此 BeanPrimary Bean DataSource defaultDs() { ... }编程式获取context.getBean(...)无法使用注入的特殊场景UserRepository repo context.getBean(UserRepository.class);注入配置值Value(${key})读取 application.properties 中的值Value(${db.url}) private String url;二、配对代码示例1. 组件扫描Component/Service/Repository/Controller注入容器ComponentpublicclassMyHelper{publicvoidhelp(){System.out.println(Helping...);}}ServicepublicclassUserService{publicvoidcreateUser(){// 业务逻辑}}RepositorypublicclassUserRepository{publicUserfindById(Longid){// 数据库操作returnnull;}}ControllerpublicclassUserController{publicStringlistUsers(){returnusers;}}取出方法紧跟在注入之后// 取出 ComponentServicepublicclassSomeService{AutowiredprivateMyHelpermyHelper;// 从容器取出 MyHelperpublicvoidexecute(){myHelper.help();}}// 取出 ServiceServicepublicclassOrderService{AutowiredprivateUserServiceuserService;// 取出 UserService}// 取出 Repository构造器注入推荐ServicepublicclassPaymentService{privatefinalUserRepositoryuserRepository;publicPaymentService(UserRepositoryuserRepository){this.userRepositoryuserRepository;// 构造器注入取出}}// 取出 Controller通常由 Spring MVC 自动处理也可手动获取ComponentpublicclassStartupRunnerimplementsCommandLineRunner{AutowiredprivateApplicationContextcontext;Overridepublicvoidrun(String...args){UserControllercontrollercontext.getBean(UserController.class);System.out.println(controller.listUsers());}}2. 配置类 Bean注入容器ConfigurationpublicclassAppConfig{BeanpublicDataSourcedataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/test);ds.setUsername(root);ds.setPassword(password);returnds;}Bean(namerestTemplate)publicRestTemplaterestTemplate(){returnnewRestTemplate();}}取出方法ServicepublicclassUserService{privatefinalDataSourcedataSource;// 构造器注入取出 DataSourcepublicUserService(DataSourcedataSource){this.dataSourcedataSource;}publicvoidquery()throwsSQLException{ConnectionconndataSource.getConnection();// ...}}ServicepublicclassApiService{AutowiredQualifier(restTemplate)// 按 Bean 指定的名称取出privateRestTemplaterestTemplate;}3.Import导入其他配置类注入容器// DatabaseConfig.javaConfigurationpublicclassDatabaseConfig{BeanpublicDataSourcedataSource(){returnnewHikariDataSource();}}// CacheConfig.javaConfigurationpublicclassCacheConfig{BeanpublicRedisTemplateString,ObjectredisTemplate(){returnnewRedisTemplate();}}// 主配置类导入上述两个配置ConfigurationImport({DatabaseConfig.class,CacheConfig.class})publicclassAppConfig{// 此时 dataSource 和 redisTemplate 都会被注册}取出方法ServicepublicclassProductService{AutowiredprivateDataSourcedataSource;// 取出 dataSourceAutowiredprivateRedisTemplateString,ObjectredisTemplate;// 取出 redisTemplate}4. 编程式注册registerBean注入容器// 在非 Spring 管理的类中手动注册GenericApplicationContextcontextnewGenericApplicationContext();context.registerBean(myCustomBean,MyClass.class,()-newMyClass(param1));context.refresh();取出方法// 在同一上下文中手动取出MyClassbeancontext.getBean(myCustomBean,MyClass.class);bean.doSomething();5. XML 配置老项目注入容器beans.xmlbeansxmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbeaniddataSourceclasscom.zaxxer.hikari.HikariDataSourcepropertynamejdbcUrlvaluejdbc:mysql://localhost:3306/test/propertynameusernamevalueroot/propertynamepasswordvaluepassword//beanbeaniduserServiceclasscom.example.UserServicepropertynamerepositoryrefuserRepository//bean/beans取出方法// 在 Java 类中通过 Autowired 取出需开启 XML 配置扫描ServicepublicclassReportService{AutowiredprivateDataSourcedataSource;}6. 按名称注入重点Qualifier/Resource/Primary当容器中存在多个相同类型的 Bean 时仅靠Autowired按类型会抛出NoUniqueBeanDefinitionException。此时必须按名称指定要取出的 Bean。本节给出三种常见解决方式的完整配对示例。6.1 场景注册多个同类型的 DataSource注入容器多个同类型 Bean各自指定名称ConfigurationpublicclassDataSourceConfig{Bean(nameorderDb)publicDataSourceorderDataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/order_db);returnds;}Bean(namereportDb)publicDataSourcereportDataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/report_db);returnds;}}6.2 取出方式一QualifierAutowired推荐组合Qualifier用于按 Bean 名称精确匹配配合Autowired使用ServicepublicclassOrderService{AutowiredQualifier(orderDb)// 按名称取出 orderDbprivateDataSourceorderDataSource;publicvoiduseOrderDb()throwsSQLException{ConnectionconnorderDataSource.getConnection();// 使用订单库连接...}}6.3 取出方式二Resource(name xxx)Java 原生注解Resource是 JSR-250 规范定义的注解默认按名称注入name属性指定 Bean 名称ServicepublicclassReportService{Resource(namereportDb)// 按名称取出 reportDbprivateDataSourcereportDataSource;publicvoiduseReportDb()throwsSQLException{ConnectionconnreportDataSource.getConnection();// 使用报表库连接...}}ResourcevsQualifier的区别Resource默认按名称匹配找不到名称再按类型AutowiredQualifier是先按类型、再用名称限定。两者都能解决多 Bean 冲突可按团队规范选择。6.4 取出方式三Primary指定首选 Bean当某个 Bean 被标记为Primary在不显式指定名称时Spring 会优先注入它其余同类型 Bean 则用Qualifier按名称取出注入容器其中一个标记为PrimaryConfigurationpublicclassDataSourceConfig{BeanPrimary// 不指定名称时默认注入这个publicDataSourcedefaultDataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/default_db);returnds;}Bean(namespecialDb)publicDataSourcespecialDataSource(){HikariDataSourcedsnewHikariDataSource();ds.setJdbcUrl(jdbc:mysql://localhost:3306/special_db);returnds;}}取出方法ServicepublicclassMixedService{AutowiredprivateDataSourcedefaultDs;// 注入 Primary 的那个无需 QualifierAutowiredQualifier(specialDb)// 按名称取出 specialDbprivateDataSourcespecialDs;}6.5 小结三种按名称注入方式对比方式注解匹配规则适用场景按名称SpringQualifier(xxx)Autowired按 Bean 名称精确匹配推荐Spring 生态标准写法按名称JavaResource(name xxx)按名称匹配Java 原生希望脱离 Spring 强依赖时使用首选 BeanPrimary不指定名称时默认注入多数据源中有一个是主库/默认库三、一句话记忆放进去Component/Bean/ XMLbean拿出来Autowired/ 构造器注入 /getBean()同名冲突多个同类型 Bean 时用Qualifier(xxx)或Resource(namexxx)按名称取出默认首选用Primary。

相关新闻

最新新闻

日新闻

周新闻

月新闻