博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring扫描自定义注解的实现
阅读量:6286 次
发布时间:2019-06-22

本文共 8715 字,大约阅读时间需要 29 分钟。

hot3.png

1.定义注解

@Target({ ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Interface {    /**     * 别名数组     * @return String[],默认空字符串     */    String[] value() default "";}

2.扫描注解注册bean的处理

public class CustomerInterfaceRegistryPostProcessor implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {    private final static Logger LOG = LoggerFactory.getLogger(CustomerInterfaceRegistryPostProcessor.class);    @Override    public int getOrder() {        return Ordered.LOWEST_PRECEDENCE;    }        @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {        if (LOG.isDebugEnabled()) {            LOG.debug("postProcessBeanFactory");        }                //搜索被Interface注解的类。key为bean的id,value为bean的实例。        //beanFactory.getBeansWithAnnotation返回时通过getBean方法将bean的实例化,如果bean中autowired注解的属性没有实例化就会注入null        //Map
map = beanFactory.getBeansWithAnnotation(Interface.class); String[] ary = beanFactory.getBeanNamesForAnnotation(Interface.class); if (ary!=null && ary.length>0) { for (String beanName : ary) { //通过Spring的beanName获取bean的类型 Class
cls = beanFactory.getType(beanName); if (cls.getAnnotations()!=null && cls.getAnnotations().length>0) { for (Annotation annotation : cls.getAnnotations()) { if (annotation instanceof Interface) { Interface intfc = (Interface) annotation; //将全限定名注册为别名 this.registerAlias(beanFactory, beanName, cls.getName()); //其他别名注册 for (String row : intfc.value()) { this.registerAlias(beanFactory, beanName, row); } } } } } } } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (LOG.isDebugEnabled()) { LOG.debug("postProcessBeanDefinitionRegistry"); } } /** * 为bean注册别名 * 注意:如果别名与bean的ID冲突,放弃别名注册 * @param factory ConfigurableListableBeanFactory * @param beanName bean的ID * @param value Interface的value */ private void registerAlias(ConfigurableListableBeanFactory factory, String beanId, String value) { //防止别名覆盖bean的ID if (factory.containsBeanDefinition(value)) { if (LOG.isDebugEnabled()) { LOG.debug("[failed] because value=" + value + " is existed"); } return; } else { if (LOG.isDebugEnabled()) { LOG.debug("[success] beanId=" + beanId + ", value=" + value); } factory.registerAlias(beanId, value); } }}

3.配置spring

好了,通过自定义注解集成Component,实现bean被spring发现并注册完成了。

========================

如果不想让自定义注解集成Component可以实现吗?答案是肯定可以的,就是要自定义类扫描,这部分代码我是参考MyBatis的原理实现的。

1.定义注解(去除@Component)

@Target({ ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Interface {    /**     * 别名数组     * @return String[],默认空字符串     */    String[] value() default "";}

2.自定义类扫描

public class CustomerClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {    public CustomerClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {        super(registry, useDefaultFilters);    }        /**     * 扫描包路径,通过include和exclude等过滤条件,返回符合条件的bean定义     * 由于这个方法在父类是protected,所以只能通过继承类获取结果     * @param basePackages 需要扫描的包路径     */    public Set
doScan(String... basePackages) { return super.doScan(basePackages); }}

3.扫描注解注册bean的处理

public class CustomerInterfaceRegistryPostProcessor implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {    private final static Logger LOG = LoggerFactory.getLogger(CustomerInterfaceRegistryPostProcessor.class);    /**     * 搜索条件:Interface注解     */    private String annotation;    /**     * 搜索条件:扫描包路径数组     */    private String[] basePackage;        public CustomerInterfaceRegistryPostProcessor() {        super();        this.annotation = Interface.class.getName();        this.basePackage = new String[] {"net.zhust.spring", "net.zhust.common"};    }    public CustomerInterfaceRegistryPostProcessor(String annotation, String[] basePackage) {        super();        this.annotation = annotation;        this.basePackage = basePackage;    }    @Override    public int getOrder() {        return Ordered.LOWEST_PRECEDENCE;    }        private Set
getBeanDefinitionHolderSet(String...basePackages) { Set
result = null; BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); BondeClassPathBeanDefinitionScanner scanner = new BondeClassPathBeanDefinitionScanner(registry, false); final String annotationType = this.annotation; //配置过滤条件 TypeFilter includeFilter = new TypeFilter(){ @Override public boolean match(MetadataReader arg0, MetadataReaderFactory arg1) throws IOException { boolean result = false; //拥有annotationInterface指定的注解的类(非抽象) if (arg0.getClassMetadata().isConcrete() && arg0.getAnnotationMetadata().hasAnnotation(annotationType)) { result = true; } return result; } }; scanner.addIncludeFilter(includeFilter); result = scanner.doScan(basePackages); return result; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (LOG.isDebugEnabled()) { LOG.debug("postProcessBeanFactory"); } DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory; Set
beans = this.getBeanDefinitionHolderSet(this.basePackage); for (BeanDefinitionHolder bdh : beans) { //获取bean的类型(经测试此时,bean可以操作) try { Class
cls = Class.forName(bdh.getBeanDefinition().getBeanClassName()); cls.getInterfaces(); if (cls.getAnnotations()!=null && cls.getAnnotations().length>0) { for (Annotation annotation : cls.getAnnotations()) { if (annotation instanceof Interface) { Interface intfc = (Interface) annotation; //将全限定名注册为别名 this.registerAlias(beanFactory, bdh.getBeanName(), cls.getName()); //其他别名注册 for (String row : intfc.value()) { this.registerAlias(beanFactory, bdh.getBeanName(), row); } //如果不做registerBeanDefinition,那么bean内的注解会无效(如Autowired) RootBeanDefinition rbd = new RootBeanDefinition(cls); dlbf.registerBeanDefinition(bdh.getBeanName(), rbd); } } } } catch(Exception ex) { ex.printStackTrace(); } } } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (LOG.isDebugEnabled()) { LOG.debug("postProcessBeanDefinitionRegistry"); } } /** * 为bean注册别名 * 注意:如果别名与bean的ID冲突,放弃别名注册 * @param factory ConfigurableListableBeanFactory * @param beanName bean的ID * @param value Interface的value */ private void registerAlias(ConfigurableListableBeanFactory factory, String beanId, String value) { //防止别名覆盖bean的ID if (factory.containsBeanDefinition(value)) { if (LOG.isDebugEnabled()) { LOG.debug("[failed] because value=" + value + " is existed"); } return; } else { if (LOG.isDebugEnabled()) { LOG.debug("[success] beanId=" + beanId + ", value=" + value); } factory.registerAlias(beanId, value); } }}

4.配置spring

net.zhust.spring
net.zhust.common

好了,就那么简单!

转载于:https://my.oschina.net/u/131091/blog/1637898

你可能感兴趣的文章
nginx反向代理
查看>>
操作系统真实的虚拟内存是什么样的(一)
查看>>
hadoop、hbase、zookeeper集群搭建
查看>>
python中一切皆对象------类的基础(五)
查看>>
modprobe
查看>>
android中用ExpandableListView实现三级扩展列表
查看>>
%Error opening tftp://255.255.255.255/cisconet.cfg
查看>>
java读取excel、txt 文件内容,传到、显示到另一个页面的文本框里面。
查看>>
《从零开始学Swift》学习笔记(Day 51)——扩展构造函数
查看>>
python多线程队列安全
查看>>
[汇编语言学习笔记][第四章第一个程序的编写]
查看>>
android 打开各种文件(setDataAndType)转:
查看>>
补交:最最原始的第一次作业(当时没有选上课,所以不知道)
查看>>
Vue实例初始化的选项配置对象详解
查看>>
PLM产品技术的发展趋势 来源:e-works 作者:清软英泰 党伟升 罗先海 耿坤瑛
查看>>
vue part3.3 小案例ajax (axios) 及页面异步显示
查看>>
浅谈MVC3自定义分页
查看>>
.net中ashx文件有什么用?功能有那些,一般用在什么情况下?
查看>>
select、poll、epoll之间的区别总结[整理]【转】
查看>>
CSS基础知识(上)
查看>>