spring容器启动时扫描指定的包下面的class

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012727852/article/details/82800599

思路:

  1. 实现BeanFactoryPostProcessor接口、ResourceLoaderAware接口。
  2. 在实现类中定义MetadataReaderFactory、ResourcePatternResolver变量。
  3. 在ResourceLoaderAware接口的setResourceLoader方法中使用SimpleMetadataReaderFactory和ResourcePatternUtils.getResourcePatternResolver分别初始化步骤【2】中的2个变量。
  4. 在BeanFactoryPostProcessor的postProcessBeanFactory中实现业务逻辑。
  5. 根据自己的需要的信息来过滤类元素信息。
  • 通过resourcePatternResolver.getResources(locationPattern)获取所有Resource列表。      
  • 通过metadataReaderFactory.getMetadataReader(classResource)获取MetadataReader,metadataReader.getClassMetadata()可以获取类的元数据信息。

示例代码:

/**
 * @description: 把rpc服务发布成SpringBean的注册器,实现服务本地化,使用者只需要把接口@Autowired即可
 * @author: gongqi
 * @create: 2018/09/10 11:46
 */
public class RpcToSpringBeanRegister implements BeanFactoryPostProcessor, ResourceLoaderAware {

    private static final Logger logger = LoggerFactory.getLogger(RpcToSpringBeanRegister.class);
    //
    protected MetadataReaderFactory metadataReaderFactory;
    protected ResourcePatternResolver resourcePatternResolver;
    private String packageToScan;



    public RpcToSpringBeanRegister(String packageToScan){
        this.packageToScan=packageToScan;
    }



    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            //获取所有的资源文件
            Resource[] classResources = resourcePatternResolver.getResources(getLocationPattern());
            for (Resource classResource : classResources) {
                //
                MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(classResource);
                String className = metadataReader.getClassMetadata().getClassName();
                Class<?> clazz = ClassUtils.forName(className, beanFactory.getBeanClassLoader());
                //如果接口上加了@CloudService注解则把接口发布成代理
                if (AnnotationUtils.isAnnotationDeclaredLocally(CloudService.class, clazz)) {
                    String serviceName = getServiceName(clazz);
                    Object serviceProxy = getServiceProxy(clazz, beanFactory);
                    Assert.notNull(serviceName, "'beanName' must not be null");
                    if(null==beanFactory.getSingleton(serviceName)) {
                        logger.info("正在注册rpc服务到spring上下文:"+serviceName);
                        beanFactory.registerSingleton(serviceName, serviceProxy);
                    }
                }
            }
        } catch (Exception e) {
            throw new FatalBeanException(e.getMessage(), e);
        }
    }


    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.metadataReaderFactory = new SimpleMetadataReaderFactory(resourceLoader);
        this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
    }


    /**
     * 获取服务的代理对象
     * @param serviceClass
     * @param beanFactory
     * @return
     */
    protected Object getServiceProxy(Class<?> serviceClass, ConfigurableListableBeanFactory beanFactory)  {
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.addInterface(serviceClass);
        //
        //生成拦截器
        RpcInvokeInterceptor invokeInterceptor=new RpcInvokeInterceptor(serviceClass);
        //
        proxyFactory.addAdvice(invokeInterceptor);
        return proxyFactory.getProxy(beanFactory.getBeanClassLoader());
    }



    /**
     * 获取资源的路径
     * @return
     */
    protected String getLocationPattern() {
        return ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + ClassUtils.convertClassNameToResourcePath(packageToScan) + "/**/*.class";
    }


    /**
     * spring ByName方式注入的名称
     * @param serviceClass
     * @return
     */
    protected String getServiceName(Class<?> serviceClass) {
        return StringUtils.uncapitalize(serviceClass.getSimpleName());
    }
}

BeanFactoryPostProcessor、ResourceLoaderAware、MetadataReaderFactory、ResourcePatternResolver的作用介绍请参照【spring学习里】的对应的帖子。

猜你喜欢

转载自blog.csdn.net/u012727852/article/details/82800599