您的位置:首页 > 汽车 > 新车 > @Component 注解高端玩法【策略模式】

@Component 注解高端玩法【策略模式】

2024/9/24 8:52:30 来源:https://blog.csdn.net/zhengzhaoyang122/article/details/140892575  浏览:    关键词:@Component 注解高端玩法【策略模式】

优质博文:IT-BLOG-CN

在这里插入图片描述

Spring框架中,@Component注解本身并不支持直接通过注解参数来定义一个key值。不过,你可以通过自定义注解和@Qualifier注解来实现类似的功能。

以下是一个示例,展示如何通过自定义注解和@Qualifier来实现将不同的实现类注入到Map中,并为每个实现类定义不同的key值。

一、定义接口和实现类

首先,定义一个接口和它的多个实现类。

MyService.java

public interface MyService {void execute();
}

MyServiceImpl1.java

import org.springframework.stereotype.Component;@Component("service1")
public class MyServiceImpl1 implements MyService {@Overridepublic void execute() {System.out.println("Executing MyServiceImpl1");}
}

MyServiceImpl2.java

import org.springframework.stereotype.Component;@Component("service2")
public class MyServiceImpl2 implements MyService {@Overridepublic void execute() {System.out.println("Executing MyServiceImpl2");}
}

自动注入所有实现类到Map

接下来,在需要使用这些实现类的地方,使用@Autowired注解和一个 Map<String, MyService>来自动注入所有实现类。

MyServiceConsumer.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Map;@Component
public class MyServiceConsumer {@Autowiredprivate Map<String, MyService> myServices;public void executeAll() {for (Map.Entry<String, MyService> entry : myServices.entrySet()) {System.out.println("Executing service with key: " + entry.getKey());entry.getValue().execute();}}
}

当我们可以拿到一个Map的时候,就可以根据客户端传递过来的key获取到对应的实现类进行处理了。

自动注入所有实现类List 接下来,在需要使用这些实现类的地方,使用@Autowired注解和一个ListMap来自动注入所有实现类。

MyServiceConsumer.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.List;@Component
public class MyServiceConsumer {@Autowiredprivate final List<MyService> myServices;public void executeAll() {for (MyService myService : myServices) {myService.execute();}}
}

最后,配置Spring应用程序上下文并执行所得实现类。

Application.javaimport org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}@Beanpublic CommandLineRunner commandLineRunner(ApplicationContext ctx) {return args -> {MyServiceConsumer myServiceConsumer = ctx.getBean(MyServiceConsumer.class);myServiceConsumer.executeAll();};}
}

二、@Component 和 @Qualifier 区别

Spring框架中,@Qualifier@Component是两个常用的注解,但它们有不同的用途和作用。

【1】@Component @Component是一个通用的Spring组件注解。它用于将一个类标记为Spring的组件,使其能够被Spring容器自动检测和注册为一个Bean。这个注解通常用于那些没有特定角色的类。

示例:

import org.springframework.stereotype.Component;@Component
public class MyService {// 业务逻辑
}

Spring扫描类路径时,带有@Component注解的类会被自动注册为Spring容器中的Bean

【2】@Qualifier @Qualifier注解通常与@Autowired注解一起使用,用于消除Bean注入时的歧义。当有多个相同类型的Bean可供注入时,@Qualifier可以指定要注入的具体Bean

示例:假设我们有两个实现了相同接口的类:

import org.springframework.stereotype.Component;@Component
public class ServiceA implements MyService {// 实现
}@Component
public class ServiceB implements MyService {// 实现
}
import org.springframework.stereotype.Component;

如果我们在某个地方自动注入MyService,会产生歧义:

@Autowired
private MyService myService; // Spring 不知道注入 ServiceA 还是 ServiceB

这时,我们可以使用@Qualifier来指定具体的Bean

@Autowired
@Qualifier("serviceA")
private MyService myService; // 明确指定注入 ServiceA

在这个例子中,"serviceA"ServiceA类的默认Bean名称(类名首字母小写)。

三、源码

Component注解的源码实现主要涉及到两个方面:自动扫描和注册。

首先,Spring框架通过类路径扫描机制自动扫描带有Component注解的类。这是通过使用Java的反射机制实现的。下面是Component注解的简化源码示例:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {}

@Component注解的元注解中,@Retention注解表示Component注解的生命周期为运行时;@Target注解表示Component注解可以标记在类上。

接下来,Spring框架通过BeanDefinition对象将扫描到的类注册到Spring容器中。BeanDefinition包含了类的一些元数据信息,如类名、类的全限定名、类的父类、类实现的接口等。下面是BeanDefinition的简化源码示例:

public interface BeanDefinition {String getBeanName();String getBeanClassName();Class<?> getBeanClass();Class<?>[] getInterfaces();Class<?> getSuperClass();// ...省略其他方法
}

Spring框架通过解析Component注解,将扫描到的类封装成BeanDefinition对象,并将其注册到BeanFactory中。BeanFactorySpring容器的核心接口,可以通过该接口获取和管理BeanDefinition对象。

Component注解的解析和注册过程一般在Spring容器启动时进行。Spring框架会扫描指定的包路径下的所有类,并解析其中的Component注解,将其注册为BeanDefinition对象。开发者可以通过配置文件指定要扫描的包路径,也可以使用@ComponentScan注解指定扫描范围。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com