Springboot 扫描自定义注解放到List中

326 阅读1分钟

使用场景:

  1. 添加中间件,配置某个注解的自定义扫描路径,例如 @Refrence,Seata 的 @Refrence。
  2. 使用自定义注解,配置自定义注解的扫描路径。

配置代码:

扫描加载类

IgnoreTenantTablesImportSelector.java

package com.leelen.hermes.mybatis.anno;

import com.leelen.hermes.mybatis.constant.TenantConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;

import java.util.Set;

/**
 * @author linqy@leelen.cn
 * @version 1.0.0
 * @ClassName IgnoreTenantTablesImportSelector.java
 * @Description
 * @createTime 2023年04月20日 20:21:00
 */
@Slf4j
public class IgnoreTenantTablesImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 不使用默认的TypeFilter
        ClassPathScanningCandidateComponentProvider provider =
                new ClassPathScanningCandidateComponentProvider(false);
        // 添加扫描规律规则,这里指定了内置的注解过滤规则
        provider.addIncludeFilter(new AnnotationTypeFilter(IgnoreTenantTables.class));
        // 扫描指定包,如果有多个包,这个过程可以执行多次
        String[] packages = getPackageToScan(annotationMetadata);
        for (String aPackage : packages) {
            Set<BeanDefinition> beanDefinitionSet = provider.findCandidateComponents(aPackage);
            beanDefinitionSet.forEach(beanDefinition -> {
                String tableName = getTableNameByAnntation(beanDefinition);
                TenantConstant.ignoreTables.add(tableName);
            });
        }

        return new String[0];
    }

    private String[] getPackageToScan(AnnotationMetadata metadata) {
        //通过自定义注解获取自定义包路径
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                metadata.getAnnotationAttributes(IgnoreTenantTablesScan.class.getName()));
        String[] basePackages = attributes.getStringArray("basePackages");
        if (basePackages.length != 0) {
            return basePackages;
        }
        return new String[]{ClassUtils.getPackageName(metadata.getClassName())};
    }

    private String getTableNameByAnntation(BeanDefinition definition) {
        String beanClassName = definition.getBeanClassName();
        try {
            Class<?> aClass = Class.forName(beanClassName);
            IgnoreTenantTables annotation = aClass.getAnnotation(IgnoreTenantTables.class);
            if (annotation == null) {
                return null;
            }
            //获取到注解name的值并返回
            return annotation.tableName();
        } catch (ClassNotFoundException e) {
            log.error("ClassNotFoundException", e);
        }
        return null;
    }
}

自定义注解

IgnoreTenantTablesScan.java

package com.leelen.hermes.mybatis.anno;

import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

/**
 * @author linqy@leelen.cn
 * @version 1.0.0
 * @ClassName IGnoreTenantyablesScan.java
 * @Description
 * @createTime 2023年04月20日 19:41:00
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Import(IgnoreTenantTablesImportSelector.class)
@Documented
public @interface IgnoreTenantTablesScan {
    String[] basePackages() default {};
}

IgnoreTenantTables.java

package com.leelen.hermes.mybatis.anno;

import java.lang.annotation.*;

/**
 * @author linqy@leelen.cn
 * @version 1.0.0
 * @ClassName IgnoreTenantTables.java
 * @Description
 * @createTime 2023年04月20日 19:37:00
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreTenantTables {
    String tableName() default "";
}

用法

标注在某个

@IgnoreTenantTables(tableName="t_user")

@Getter
@Setter
@TableName("t_user")
@IgnoreTenantTables(tableName="t_user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 用户主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    }

启动类添加注解

@IgnoreTenantTablesScan(basePackages = {"com.leelen.hermes.**"})

@SpringBootApplication
@MapperScan(basePackages = {"com.leelen.hermes.demo.dao"})
@IgnoreTenantTablesScan(basePackages = {"com.leelen.hermes.**"})

public class MybatisplusApplication {

   public static void main(String[] args)
   {
      SpringApplication application = new SpringApplication(MybatisplusApplication.class);
      application.run(args);
   }

}