欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈自定义注解在Spring中的应用

程序员文章站 2024-02-11 20:35:16
1.java自定义注解与spring java注解作为程序元素(类、成员变量、成员方法等)的一种元数据信息,对程序本身的执行不会产生影响。通过自定义注解,可以给程序元素添...

1.java自定义注解与spring

java注解作为程序元素(类、成员变量、成员方法等)的一种元数据信息,对程序本身的执行不会产生影响。通过自定义注解,可以给程序元素添加特殊的声明。

spring作为构建企业级应用的平台,提供了丰富的功能。将java的自定义注解与spring结合,在特定场景下实现注解的解析、处理,可以降低应用的耦合度,提高程序的可扩展性。

2.应用场景

下面总结几种应用场景,仅说明大致思路(ps:并非所有场景都在项目中实践过)

2.1登陆、权限拦截

在web项目中,登陆拦截和权限拦截是一个老生常谈的功能。通过自定义登陆注解或权限注解,在自定义拦截器中解析注解,实现登陆和权限的拦截功能。

这种使用方式,配置简单,灵活度高,代码耦合度低。

2.2定时任务管理

在系统构建过程中,会有各种定时任务的需求,而定时任务的集中管理,可以更高效维护系统的运行。

通过java注解官方文档repeatingannotations章节中的自定义的定时任务注解,可以实现业务方法的定时任务声明。结合spring的容器后处理器beanpostprocessor(ps:spring容器后处理器下篇再说),解析自定义注解。解析后的注解信息再使用quartzapi构建运行时定时任务,即可完成定时任务的运行时创建和集中管理。

这种方式能避免定义quartz定时任务的配置,提高系统扩展性。

2.3多数据源路由的数据源指定

spring提供的abstractroutingdatasource实现多数据源的动态路由,可应用在主从分离的架构下。通过对不同的方法指定不同的数据源,实现数据源的动态路由(例如:读方法走从库数据源,写方法走主库数据源)。而如何标识不同的方法对应的数据源类型,则可使用自定义注解实现。通过解析方法上声明的自定义注解对应的数据源类型,实现数据源的路由功能。

这种方式避免了对方法的模式匹配解析(例如:select开头、update开头等),声明更加灵活。

自定义注解

先看一个最简单的例子,在使用springweb应用中的过程中,大家免不了会使用@controller,@service,@repository等注解来定义javabean。那么怎么自己定义一个注解,spring可以自动加载呢。所以就有了第一个例子。

@target({ elementtype.type })
@retention(retentionpolicy.runtime)
@documented
@component
public @interface mycomponent {
  string value() default "";
}
@configuration
public class componentannotationtest {
 public static void main(string[] args) {
  annotationconfigapplicationcontext annotationconfigapplicationcontext = new annotationconfigapplicationcontext();
annotationconfigapplicationcontext.register(componentannotationtest.class);
  annotationconfigapplicationcontext.refresh();
  injectclass injectclass = annotationconfigapplicationcontext.getbean(injectclass.class);
    injectclass.print();
 }
 @mycomponent
 public static class injectclass {
  public void print() {
    system.out.println("hello world");
  }
 }
}

运行这个例子,就会发现,@mycomponent 注解的类,也被spring加载进来了,而且可以当成普通的javabean正常的使用。查看spring的源码会发现,spring是使用classpathscanningcandidatecomponentprovider扫描package,这个类有这样的注释

a component provider that scans the classpath from a base package. 
it then applies exclude and include filters to the resulting classes to find candidates.

这个类的 registerdefaultfilters 方法有这样几行代码

protected void registerdefaultfilters() {  
  this.includefilters.add(new annotationtypefilter(component.class));
  classloader cl = classpathscanningcandidatecomponentprovider.class.getclassloader();
  try {  
   this.includefilters.add(new annotationtypefilter(((class<? extends annotation>) classutils.forname("javax.annotation.managedbean", cl)), false)); 
   logger.debug("jsr-250 'javax.annotation.managedbean' found and supported for component scanning"); 
  }  catch (classnotfoundexception ex) {   
   // jsr-250 1.1 api (as included in java ee 6) not available - simply skip.  
  }  
  try {   
   this.includefilters.add(new annotationtypefilter(((class<? extends annotation>) classutils.forname("javax.inject.named", cl)), false));   
   logger.debug("jsr-330 'javax.inject.named' annotation found and supported for component scanning");  
  } 
  catch (classnotfoundexception ex) {   
  // jsr-330 api not available - simply skip. 
  }
}

这里就会发现spring在扫描类信息的使用只会判断被@component注解的类,所以任何自定义的注解只要带上@component(当然还要有string value() default "";的方法,因为spring的bean都是有beanname唯一标示的),都可以被spring扫描到,并注入容器内。

总结

以上就是本文关于浅谈自定义注解在spring中的应用的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!