11.启动机制和注解驱动

启动机制和注解驱动

实现注解驱动

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;
    }
}