启动机制和注解驱动
实现注解驱动
1 主动扫描
- 让开发者指定要扫描的路径,然后遍历所有的类文件,针对有注解的类的文件,执行自定义的操作
2 监听 Bean 加载
- 在Spring项目中,可以通过实现 BeanPostProcessor 接口,在Bean初始化后执行自定义的操作
1.代码实现
1.1 启动机制
1.1.1 新建服务注册信息类
/**
* 服务注册信息类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ServiceRegisterInfo<T> {
/**
* 服务名称
*/
private String serviceName;
/**
* 实现类
*/
private Class<? extends T> implClass;
}
1.1.2 新建ProviderBootstrap启动类
/**
* 服务提供者启动类
*/
public class ProviderBootstrap {
/**
* 初始化
* @param serviceRegisterInfos
*/
public static void init(List<ServiceRegisterInfo> serviceRegisterInfos){
// RPC 框架初始化(配置和注册中心)
RpcApplication.init();
// 全局配置
final RpcConfig rpcConfig = RpcApplication.getRpcConfig();
// 注册服务
for (ServiceRegisterInfo<?> serviceRegisterInfo : serviceRegisterInfos) {
String serviceName = serviceRegisterInfo.getServiceName();
// 本地注册,注册服务
LocalRegistry.register(serviceName,serviceRegisterInfo.getImplClass());
// 注册服务到注册中心
RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());
ServiceMetaInfo serviceMetaInfo = new ServiceMetaInfo();
serviceMetaInfo.setServiceName(serviceName);
serviceMetaInfo.setServiceHost(rpcConfig.getServerHost());
serviceMetaInfo.setServicePort(rpcConfig.getServerPort());
try {
registry.register(serviceMetaInfo);
} catch (Exception e) {
throw new RuntimeException(serviceName + " 服务注册失败", e);
}
}
// 启动 web 服务
VertxTcpServer vertxTcpServer = new VertxTcpServer();
vertxTcpServer.doStart(RpcApplication.getRpcConfig().getServerPort());
}
}
1.1.3 服务提供者
/**
* 服务提供者示例
*/
public class ProviderExample {
public static void main( String[] args ){
// 要注册的服务
List<ServiceRegisterInfo> serviceRegisterInfoList = new ArrayList<>();
// 将服务添加到 serviceRegisterInfoList
ServiceRegisterInfo serviceRegisterInfo = new ServiceRegisterInfo(UserService.class.getName(),UserServiceImpl.class);
serviceRegisterInfoList.add(serviceRegisterInfo);
// 服务提供者初始化
ProviderBootstrap.init(serviceRegisterInfoList);
}
}
1.1.4 服务消费者启动类
/**
* 服务提供者启动类
*/
public class ConsumerBootstrap {
/**
* 初始化
*/
public static void init(){
// RPC 框架初始化(配置和注册中心)
RpcApplication.init();
}
}
1.1.5 服务消费者
/**
* 服务消费者启动类
*
*/
public class ConsumerExample {
public static void main( String[] args ){
// 服务消费者初始化
ConsumerBootstrap.init();
// 创建静态代理
// UserService userService = new UserServiceProxy();
// 创建JDK动态代理
UserService userService = JdkServiceProxyFactory.getProxy(UserService.class);
// 创建CGlib动态代理
// UserService userService = CGlibServiceProxyFactory.getProxy(UserService.class);
User user1 = new User();
user1.setName("todaysaturday");
User newUser1 = userService.getUser(user1);
if(newUser1 == null){
System.out.println("user1 == null");
}else{
System.out.println("user1 == "+ newUser1.getName());
}
User user2 = new User();
user2.setName("todaysaturday");
User newUser2 = userService.getUser(user2);
if(newUser2 == null){
System.out.println("user2 == null");
}else{
System.out.println("user2 == "+ newUser2.getName());
}
User user3 = new User();
user3.setName("todaysaturday");
User newUser3 = userService.getUser(user3);
if(newUser3 == null){
System.out.println("user3 == null");
}else{
System.out.println("user3 == "+ newUser3.getName());
}
}
}
2.注解驱动
2.1 创建todaysaturday-rpc-spring-boot-starter 项目
引入rpc maven依赖
<dependency>
<!-- RPC 框架 -->
<groupId>com.todaysaturday</groupId>
<artifactId>todaysaturday-rpc-core10.0</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2.2 定义注解
2.2.1 参考Dubbo注解
@EnableDubbo
- 在 Spring Boot 主应用类上使用,用于启用 Dubbo 功能。
@DubboComponentScan
- 在 Spring Boot 主应用类上使用,用于指定 Dubbo 组件扫描的包路径。
@DubboReference
- 在消费者中使用,用于声明 Dubbo 服务引用。
@DubboService
- 在提供者中使用,用于声明 Dubbo 服务。
@DubboMethod
- 在提供者和消费者中使用,用于配置 Dubbo 方法的参数、超时时间等。
@DubboTransported
- 在 Dubbo 提供者和消费者中使用,用于指定传输协议和参数,例如传输协议的类型、端口等。
2.2.2 @EnableRpc 注解
- 用于全局标识项目需要引入 RPC 框架,执行初始化方法
/**
* 启用 RPC 注解
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({RpcInitBootstrap.class, RpcProviderBootstrap.class, RpcConsumerBootstrap.class})
public @interface EnableRpc {
/**
* 需要启动 server
* @return
*/
boolean needServer() default true;
}
2.2.3 @RpcReference
- 服务提供者注解,在需要注册和提供的服务类上使用
/**
* 服务提供者注解(用于注册服务)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface RpcReference {
/**
* 服务接口类
*/
Class<?> interfaceClass() default void.class;
/**
* 版本
*/
String serviceVersion() default RpcConstant.DEFAULT_SERVICE_VERSION;
/**
* 负载均衡器
*/
String loadBalancer() default LoadBalancerKeys.ROUND_ROBIN;
/**
* 重试策略
*/
String retryStrategy() default RetryStrategyKeys.NO;
/**
* 容错策略
*/
String tolerantStrategy() default TolerantStrategyKeys.FAIL_FAST;
/**
* 模拟调用
*/
boolean mock() default false;
}
2.2.4 @RpcService
- 服务消费者注解,在需要注入服务代理对象的属性上使用,类似 spring 的 @Resource注解
/**
* 服务提供者注解(用于注册服务)
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface RpcService {
/**
* 服务接口类
*/
Class<?> interfaceClass() default void.class;
/**
* 版本
*/
String serviceVersion() default RpcConstant.DEFAULT_SERVICE_VERSION;
}
2.3 新建启动类
2.3.1 Rpc 框架全局启动类 RpcInitBootstrap
/**
* Rpc 框架启动
*/
@Slf4j
public class RpcInitBootstrap implements ImportBeanDefinitionRegistrar {
/**
* Spring 初始化时执行,初始化RPC框架
* @param importingClassMetadata
* @param registry
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
// 获取 EnableRpc 注解的属性值
boolean needServer = (boolean) importingClassMetadata
.getAnnotationAttributes(EnableRpc.class.getName())
.get("needServer");
// Rpc 框架初始化(配置和注册中心)
RpcApplication.init();
// 全局配置
final RpcConfig rpcConfig = RpcApplication.getRpcConfig();
// 启动服务器
if(needServer){
VertxTcpServer vertxTcpServer = new VertxTcpServer();
vertxTcpServer.doStart(rpcConfig.getServerPort());
}else{
log.info("不启动 server");
}
}
}
2.3.2 Rpc 服务提供者启动类 RpcProviderBootstrap
/**
* Rpc 服务提供者启动类
*/
@Slf4j
public class RpcProviderBootstrap implements BeanPostProcessor {
/**
* Bean 初始化后注入服务
* @param bean
* @param beanName
* @return
* @throws BeanException
*/
@Override
public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException {
Class<?> beanClass = bean.getClass();
// 遍历对象的所有属性
RpcService rpcService = beanClass.getAnnotation(RpcService.class);
if(rpcService !=null){
// 需要注册服务
// 1.获取服务基本信息
Class<?> interfaceClass = rpcService.interfaceClass();
// 默认值处理
if(interfaceClass == void.class){
interfaceClass = beanClass.getInterfaces()[0];
}
String serviceName = interfaceClass.getName();
String serviceVersion = rpcService.serviceVersion();
// 2.注册服务
LocalRegistry.register(serviceName,beanClass);
// 全局配置
final RpcConfig rpcConfig = RpcApplication.getRpcConfig();
// 注册服务到注册中心
RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());
ServiceMetaInfo serviceMetaInfo = new ServiceMetaInfo();
serviceMetaInfo.setServiceName(serviceName);
serviceMetaInfo.setServiceVersion(serviceVersion);
serviceMetaInfo.setServiceHost(rpcConfig.getServerHost());
serviceMetaInfo.setServicePort(rpcConfig.getServerPort());
try {
registry.register(serviceMetaInfo);
} catch (Exception e) {
throw new RuntimeException(serviceName + " 服务注册失败", e);
}
}
return BeanPostProcessor.super.postProcessAfterInitialization(bean,beanName);
}
}
2.3.3 Rpc 服务消费者启动类 RpcConsumerBootstrap
/**
* Rpc 服务消费者启动类
*/
public class RpcConsumerBootstrap implements BeanPostProcessor {
/**
* Bean 初始化后注入服务
* @param bean
* @param beanName
* @return
* @throws BeanException
*/
@Override
public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansException {
Class<?> beanClass = bean.getClass();
// 遍历对象的所有属性
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field field : declaredFields) {
// 查找RpcReference注解
RpcReference rpcReference = field.getAnnotation(RpcReference.class);
if(rpcReference != null){
// 为属性生成代理对象
Class<?> interfaceClass = rpcReference.interfaceClass();
if(interfaceClass == void.class){
interfaceClass = field.getType();
}
// 设置字段可访问性
field.setAccessible(true);
// 获取代理对象
Object proxyObject = JdkServiceProxyFactory.getProxy(interfaceClass);
try {
// 注入代理对象
field.set(bean,proxyObject);
field.setAccessible(false);
} catch (IllegalAccessException e) {
throw new RuntimeException("为字段注入代理对象失败", e);
}
}
}
// 调用父类的方法以确保其他后处理器能够继续执行
return BeanPostProcessor.super.postProcessAfterInitialization(bean,beanName);
}
}
2.4 创建modules
2.4.1 提供者和消费者引入依赖
<dependency>
<groupId>com.todaysaturday</groupId>
<artifactId>todaysaturday-rpc-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.todaysaturday</groupId>
<artifactId>example-common-core10.0</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2.4.2 提供者的入口类
@SpringBootApplication
@EnableRpc
public class ExampleSpringbootProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleSpringbootProviderApplication.class, args);
}
}
2.4.3 消费者的入口类
@SpringBootApplication
@EnableRpc
public class ExampleSpringbootConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleSpringbootConsumerApplication.class, args);
}
}
2.4.4 实现UserService
/**
* 用户服务实现类
*/
@RpcService
public class UserServiceImpl implements UserService {
@Override
public User getUser(User user) {
System.out.println("用户名:"+user.getName());
return user;
}
@Override
public short getNumber() {
return 0;
}
}