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@Componentpublic @interface MyComponent { String value() default "";} @Configurationpublic 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中的應用的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!