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

 更新时间:2017年12月25日 14:13:07   作者:liuxigiant  
这篇文章主要介绍了浅谈自定义注解在Spring中的应用,具有一定借鉴价值,需要的朋友可以参考下。

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中的应用的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

相关文章

  • 防止SpringMVC拦截器拦截js等静态资源文件的解决方法

    防止SpringMVC拦截器拦截js等静态资源文件的解决方法

    本篇文章主要介绍了防止SpringMVC拦截器拦截js等静态资源文件的解决方法,具有一定的参考价值,有兴趣的同学可以了解一下
    2017-09-09
  • 解析spring-security权限控制和校验的问题

    解析spring-security权限控制和校验的问题

    这篇文章主要介绍了解析spring-security权限控制和校验的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • java同步开篇入门简单介绍

    java同步开篇入门简单介绍

    java中的CountDownLatch、Semaphore、CyclicBarrier这些类又不属于锁,它们和锁又有很多共同点,都是为了协同多线程的执行,都是一种同步器,所以这里就借用同步来取名字了,也就是“同步系列”的来源。下面小编来简单介绍下
    2019-05-05
  • java正则表达式匹配所有数字的案例

    java正则表达式匹配所有数字的案例

    这篇文章主要介绍了java正则表达式匹配所有数字的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 细致解读希尔排序算法与相关的Java代码实现

    细致解读希尔排序算法与相关的Java代码实现

    这篇文章主要介绍了希尔排序算法与相关的Java代码实现,希尔排序的时间复杂度根据步长序列的不同而不同,需要的朋友可以参考下
    2016-05-05
  • Java中树的存储结构实现示例代码

    Java中树的存储结构实现示例代码

    本篇文章主要介绍了Java中树的存储结构实现示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • IntelliJ IDEA 2022.1.1 沒有CVS的过程分析

    IntelliJ IDEA 2022.1.1 沒有CVS的过程分析

    这篇文章主要介绍了IntelliJ IDEA 2022.1.1 沒有CVS的过程解析,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • JavaWeb如何实现限制单个账号多处登录

    JavaWeb如何实现限制单个账号多处登录

    这篇文章主要介绍了JavaWeb如何实现限制单个账号多处登录问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java中的日期时间处理及格式化处理

    Java中的日期时间处理及格式化处理

    这篇文章主要介绍了Java中的日期时间处理及格式化处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 解决maven maven.compiler.source和maven.compiler.target的坑

    解决maven maven.compiler.source和maven.compiler.target的坑

    这篇文章主要介绍了解决maven maven.compiler.source和maven.compiler.target的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12

最新评论