BeanFactory
介绍
- 👋 Hi, I’m @DSXRIIIII
- 👀 该项目旨在帮助初学者对Bean注入方式的思考和理解👑
- ⚡ git后记得修改mq的地址和账户密码
- 📫 1870066109@qq.com
- 😄 个人博客请访问 DSXRIIIII个人博客
在项目构建中 当我们使用模板方法模式时 我们需要创建一个规范化接口 定义方法的行为准则
此时我们使用注解@Service或者@Component注解时 可能会出现一些问题
设计代码
//定义接口
/**
* @ProjectName: `Bean`Map
* @Description: 定义行为规范
* @Author: DSXRIIIII
* @CreateDate: 2024/7/19 17:09
* @Email: lihh53453@hundsun.com
*/
public interface IService {
public void doLogin();
public void doChange();
}
//定义实现类
@Service
public class UserService implements IService {
@Override
public void doLogin() {
System.out.println("调用用户doLogin方法( •̀ ω •́ )✧");
}
@Override
public void doChange() {
System.out.println("调用用户doChange方法ヾ(≧ ▽ ≦)ゝ");
}
}
@Service
public class CustomerService implements IService {
@Override
public void doLogin() {
System.out.println("调用消费者doLogin方法( •̀ ω •́ )✧");
}
@Override
public void doChange() {
System.out.println("调用消费者doChange方法ヾ(≧ ▽ ≦)ゝ");
}
}
//`Bean`注入自动调用
@Component
public class ServiceInvoke {
@Resource
private IService service;
@`Bean`
public void invoke_service(){
service.doChange();
service.doLogin();
}
}
此时会报错:
:::danger
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘serviceInvoke’: Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘cn.dsxriiiii.middleware.protocol.IService’ available: expected single matching bean but found 2: customerService,userService
:::
说明此时IOC找到了两个Bean 但是不知道使用的是哪一个
方案一
使用**@Primary**
注解:可以将其中一个bean标记为@Primary
,这样当存在多个候选bean时,Spring将优先选择被标记为@Primary
的bean进行自动装配。
//添加注解
@Primary
@Service
public class UserService implements IService {
@Override
public void doLogin() {
System.out.println("调用UserService用户doLogin方法( •̀ ω •́ )✧");
}
@Override
public void doChange() {
System.out.println("调用UserService用户doChange方法ヾ(≧ ▽ ≦)ゝ");
}
}
//此时启动项目时
打印日志如下
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.12)
2024-07-19 17:27:49.344 INFO 26980 --- [ main] cn.dsxriiiii.middleware.Application : Starting Application using Java 1.8.0_401 on DESKTOP-50PSSHU with PID 26980 (D:\JAVAProject\HaHa\`Bean`Map\target\classes started by hspcadmin in D:\JAVAProject\HaHa\`Bean`Map)
2024-07-19 17:27:49.347 INFO 26980 --- [ main] cn.dsxriiiii.middleware.Application : No active profile set, falling back to 1 default profile: "default"
2024-07-19 17:27:49.873 INFO 26980 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2024-07-19 17:27:49.878 INFO 26980 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-07-19 17:27:49.878 INFO 26980 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.75]
2024-07-19 17:27:50.034 INFO 26980 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-07-19 17:27:50.034 INFO 26980 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 649 ms
调用UserService用户doChange方法ヾ(≧ ▽ ≦)ゝ
调用UserService用户doLogin方法( •̀ ω •́ )✧
2024-07-19 17:27:50.306 INFO 26980 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-19 17:27:50.314 INFO 26980 --- [ main] cn.dsxriiiii.middleware.Application : Started Application in 1.23 seconds (JVM running for 2.085)
方案二
使用**@Qualifier**
注解:如果不想或不能使用@Primary
,可以在自动装配的地方使用@Qualifier
注解来指定需要注入的具体bean的名称。
//注入的时候添加注解
@Resource
@Qualifier("customerService")
private IService service;
//输出日志
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.12)
2024-07-19 17:42:02.941 INFO 25308 --- [ main] cn.dsxriiiii.middleware.Application : Starting Application using Java 1.8.0_401 on DESKTOP-50PSSHU with PID 25308 (D:\JAVAProject\HaHa\`Bean`Map\target\classes started by hspcadmin in D:\JAVAProject\HaHa\`Bean`Map)
2024-07-19 17:42:02.946 INFO 25308 --- [ main] cn.dsxriiiii.middleware.Application : No active profile set, falling back to 1 default profile: "default"
2024-07-19 17:42:03.769 INFO 25308 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2024-07-19 17:42:03.775 INFO 25308 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-07-19 17:42:03.776 INFO 25308 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.75]
2024-07-19 17:42:03.939 INFO 25308 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-07-19 17:42:03.939 INFO 25308 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 912 ms
调用CustomerService消费者doChange方法ヾ(≧ ▽ ≦)ゝ
调用CustomerService消费者doLogin方法( •̀ ω •́ )✧
2024-07-19 17:42:04.319 INFO 25308 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-19 17:42:04.329 INFO 25308 --- [ main] cn.dsxriiiii.middleware.Application : Started Application in 1.768 seconds (JVM running for 2.738)
方案三
使用构造方法注入:当存在多个相同类型的Bean
需要注入时,可以使用构造方法注入,并将这些Bean
作为参数传递。Spring
框架会自动识别并注入所有匹配的Bean
,你可以通过在构造方法参数上使用@Qualifier
注解来区分它们。此外,Spring
允许将所有匹配的Bean
自动装配到一个Map
集合中,其中Map
的键是Bean的名称,值是Bean
实例本身
//创建Factory工厂类
//定义调用方法
public interface IServiceFactory {
void process();
}
//在实现类上 我们需要定义一个Map Spring框架可以自动注入
@Service
public class ServiceFactory implements IServiceFactory {
private final Map<String, IService> ServiceGroup;
public ServiceFactory(Map<String, IService> ServiceNodeGroup) {
this.ServiceGroup = ServiceNodeGroup;
}
@Override
public void process() {
ServiceGroup.get("userService").doLogin();
ServiceGroup.get("customerService").doLogin();
}
}
日志如下
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.12)
2024-07-19 18:08:06.972 INFO 20964 --- [ main] cn.dsxriiiii.middleware.Application : Starting Application using Java 1.8.0_401 on DESKTOP-50PSSHU with PID 20964 (D:\JAVAProject\HaHa\`Bean`Map\target\classes started by hspcadmin in D:\JAVAProject\HaHa\`Bean`Map)
2024-07-19 18:08:06.976 INFO 20964 --- [ main] cn.dsxriiiii.middleware.Application : No active profile set, falling back to 1 default profile: "default"
2024-07-19 18:08:07.731 INFO 20964 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2024-07-19 18:08:07.738 INFO 20964 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-07-19 18:08:07.738 INFO 20964 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.75]
2024-07-19 18:08:07.879 INFO 20964 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-07-19 18:08:07.879 INFO 20964 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 846 ms
调用UserService用户doLogin方法( •̀ ω •́ )✧
调用CustomerService消费者doLogin方法( •̀ ω •́ )✧
2024-07-19 18:08:08.173 INFO 20964 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-07-19 18:08:08.182 INFO 20964 --- [ main] cn.dsxriiiii.middleware.Application : Started Application in 1.61 seconds (JVM running for 2.81)