注释嵌套注释_DIY注释
注釋嵌套注釋
從Java 5開始,Java中出現了注釋。 我想做一個自己的注釋,只是為了看看需要什么。 但是,我發現它們只是接口。
有擦
接口后面沒有牙。 必須執行一些代碼。 我認為這是橡膠行之有效的方法,我真的找到了解決方法。
首先,我需要一個目標
我選擇了一個最近的熱門話題:緩存。 我不想實現JSR 109(JCache),但也不想做典型的“ Hello World”。 我選擇實現兩個注釋,一個注釋不帶任何參數,另一個注釋不帶參數。 我還需要一個緩存提供程序。 如果我要這樣做的話,還可以將真正的緩存庫加入其中。 它還遵循我的設計理念,即使用產品/庫來達成目標,而不是將所有內容都進行家庭紡。 經過仔細考慮,我選擇了hazelcast作為我的緩存引擎。 它是市場上最快的,而且是免費的。
更多決定
在選擇了目標之后,我仍然需要找出如何在它們后面扎牙的方法。 經過一番挖掘,我發現了兩種方法:
反射
幾乎每次使用反射時,我都會為編寫這么笨拙的代碼感到遺憾。 另外,要按照我想要的方式進行操作,我必須創建自己的框架。 聽起來兩個注解的工作量很大。
面向方面的編程(AOP)
這非常適合我想做的事。 AOP致力于將樣板代碼減少到一個地方。 這將很方便并且與緩存緊密結合,因為緩存可分為以下步驟:
也許這過于簡單,但總的來說是正確的。 就像所有事物一樣,細節決定成敗。
同時,回到AOP牧場
雖然我知道AOP是適合我的地方,但我對此并不了解。 我發現Spring有一個AOP庫,而眾所周知的庫是AspectJ。 AspectJ對我不熟悉,需要運行時引擎才能工作。 我對Spring更加熟悉,所以選擇了它。 在研究Spring的AOP時,我發現我必須深入研究AspectJ的注釋,因此無論如何我還是以某種形式或方式被AspectJ所困。
新概念,新詞匯
編寫方面不像編寫對象。 它們是對象,但并非如此,因此當然需要一組新的術語。 我使用的是Spring AOP文檔中的內容
我確實需要閱讀幾次該頁面才能理解所講的內容。 強烈建議您執行相同的操作,否則其余帖子聽起來像胡言亂語。
切入點的構成和建議
切入點設計很容易,因為我只對帶有注釋的方法感興趣。 它需要的建議是周圍的建議,因為如果已經進行了匹配的調用,我就需要能夠避免調用該方法。
最后的代碼
Maven Pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.darylmathison</groupId><artifactId>annotation-implementation</artifactId><version>1.0-SNAPSHOT</version><properties><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><spring.version>4.2.4.RELEASE</spring.version></properties><description>This project is an example of how to implement an annotation via Spring AOP.</description><scm><url>https://github.com/darylmathison/annotation-implementation-example.git</url><connection>scm:git:https://github.com/darylmathison/annotation-implementation-example.git</connection><developerConnection>scm:git:git@github.com:darylmathison/annotation-implementation-example.git</developerConnection></scm><issueManagement><system>GitHub</system><url>https://github.com/darylmathison/annotation-implementation-example/issues</url></issueManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version><scope>test</scope></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.8</version></dependency><dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast</artifactId><version>3.6</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies><reporting><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-project-info-reports-plugin</artifactId><version>2.7</version><reportSets><reportSet><reports><report>dependencies</report><report>index</report><report>project-team</report><report>issue-tracking</report><report>scm</report></reports></reportSet></reportSets></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-report-plugin</artifactId><version>2.18.1</version></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-javadoc-plugin</artifactId><version>2.10.3</version><reportSets><reportSet><reports><report>javadoc</report><report>test-javadoc</report></reports></reportSet></reportSets></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jxr-plugin</artifactId><version>2.5</version><configuration><linkJavadoc>true</linkJavadoc></configuration><reportSets><reportSet><reports><report>jxr</report><report>test-jxr</report></reports></reportSet></reportSets></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-changelog-plugin</artifactId><version>2.3</version><configuration><type>range</type><range>90</range></configuration></plugin></plugins></reporting> </project>注釋
快取
緩存注釋的可愛名稱,對嗎?
package com.darylmathison.ai.annotation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** Created by Daryl on 2/19/2016.*/ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface CacheMe { }CacheMeNow
package com.darylmathison.ai.annotation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/*** Created by Daryl on 2/19/2016.*/ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface CacheMeNow {String key(); }彈簧配置
我決定使用基于Java的配置,而不是像通常為了改變速度而使用的XML。 EnableAspectJAutoProxy批注是使Spring AOP開始工作的關鍵。 我一直在我旁邊,直到我讀到有關這顆小寶石的這篇文章。 有時,這是一天中最容易燃燒的事情。
AppConfig
package com.darylmathison.ai.config;import com.darylmathison.ai.cache.CacheAspect; import com.darylmathison.ai.service.FibonacciService; import com.darylmathison.ai.service.FibonacciServiceImpl; import com.hazelcast.config.Config; import com.hazelcast.config.EvictionPolicy; import com.hazelcast.config.MapConfig; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy;import java.util.HashMap; import java.util.Map;/*** Created by Daryl on 2/20/2016.*/ @Configuration @ComponentScan(basePackages = "com.darylmathison.ai") @EnableAspectJAutoProxy public class AppConfig {@Beanpublic Map<String, Object> cache() {Config config = new Config();MapConfig mapConfig = new MapConfig();mapConfig.setEvictionPercentage(50);mapConfig.setEvictionPolicy(EvictionPolicy.LFU);mapConfig.setTimeToLiveSeconds(300);Map<String, MapConfig> mapConfigMap = new HashMap<>();mapConfigMap.put("cache", mapConfig);config.setMapConfigs(mapConfigMap);HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);return instance.getMap("cache");}@Beanpublic FibonacciService fibonacci() {return new FibonacciServiceImpl();}@Beanpublic CacheAspect cacheAspect() {return new CacheAspect();} }服務編號
基于經典Spring的設計需要服務嗎? 由于Spring使用代理來實現其AOP,因此強烈建議為帶注釋的類定義一個接口以實現。
斐波那契服務
package com.darylmathison.ai.service;/*** Created by Daryl on 2/20/2016.*/ public interface FibonacciService {long calculate(int rounds);long calculateWithKey(int rounds); }FibonacciServiceImpl
package com.darylmathison.ai.service;import com.darylmathison.ai.annotation.CacheMe; import com.darylmathison.ai.annotation.CacheMeNow;/*** Created by Daryl on 2/20/2016.*/ public class FibonacciServiceImpl implements FibonacciService {@Override@CacheMepublic long calculate(int rounds) {return sharedCalculate(rounds);}@Override@CacheMeNow(key = "now")public long calculateWithKey(int rounds) {return sharedCalculate(rounds);}private static long sharedCalculate(int rounds) {long[] lastTwo = new long[] {1, 1};for(int i = 0; i < rounds; i++) {long last = lastTwo[1];lastTwo[1] = lastTwo[0] + lastTwo[1];lastTwo[0] = last;}return lastTwo[1];} }AOP的東西
這是注釋實現的核心。 其他所有內容都可以用來支持后續的工作。
系統存檔
根據Spring文檔,集中化切入點定義是一個好主意。
package com.darylmathison.ai.cache;import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut;/*** Created by Daryl on 2/20/2016.*/ @Aspect public class SystemArch {@Pointcut("@annotation(com.darylmathison.ai.annotation.CacheMe)")public void cacheMeCut() {}@Pointcut("@annotation(com.darylmathison.ai.annotation.CacheMeNow)")public void cacheMeNowCut() {} }緩存方面
周圍注釋使用切入點類的完整方法名稱來定義建議的內容。 CacheMeNow批注的建議包括一個額外條件,因此可以定義批注,以便可以讀取關鍵參數。 測試代碼中揭示了CacheMeNow中的一個設計錯誤。
package com.darylmathison.ai.cache;import com.darylmathison.ai.annotation.CacheMeNow; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired;import java.util.Map;/*** Created by Daryl on 2/20/2016.*/ @Aspect public class CacheAspect {@Autowiredprivate Map<String, Object> cache;@Around("com.darylmathison.ai.cache.SystemArch.cacheMeCut()")public Object simpleCache(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {StringBuffer keyBuffer = new StringBuffer();for(Object o: proceedingJoinPoint.getArgs()) {keyBuffer.append(o.hashCode());}String key = keyBuffer.toString();Object ret = cache.get(key);if(ret == null) {ret = proceedingJoinPoint.proceed();cache.put(key, ret);}return ret;}@Around("com.darylmathison.ai.cache.SystemArch.cacheMeNowCut() && @annotation(cacheMeNow)")public Object simpleCacheWithParam(ProceedingJoinPoint proceedingJoinPoint, CacheMeNow cacheMeNow) throws Throwable {Object ret = cache.get(cacheMeNow.key());if(ret == null) {ret = proceedingJoinPoint.proceed();cache.put(cacheMeNow.key(), ret);}return ret;} }測試代碼
顯示注釋確實引起緩存的驅動程序代碼。
斐波那契檢驗
package com.darylmathison.ai.service;import com.darylmathison.ai.config.AppConfig; import org.junit.Assert; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/*** Created by Daryl on 2/20/2016.*/ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {AppConfig.class}) public class FibonacciTest {private static final int ROUNDS = 12;private static final long ANSWER = 377;@Autowiredprivate FibonacciService fibonacci;@org.junit.Testpublic void testCalculate() throws Exception {long start = System.currentTimeMillis();Assert.assertEquals(ANSWER, fibonacci.calculate(ROUNDS));long middle = System.currentTimeMillis();Assert.assertEquals(ANSWER, fibonacci.calculate(ROUNDS));long end = System.currentTimeMillis();Assert.assertTrue((end - middle) < (middle - start));}@org.junit.Testpublic void testCalculateWithKey() throws Exception {Assert.assertEquals(ANSWER, fibonacci.calculateWithKey(ROUNDS));// This test should not passAssert.assertEquals(ANSWER, fibonacci.calculateWithKey(13));} }結論
注釋不必很難實現。 使用AOP編程,我可以用很少的代碼來實現兩個注釋。
翻譯自: https://www.javacodegeeks.com/2016/03/diy-annotations-3.html
注釋嵌套注釋
總結
以上是生活随笔為你收集整理的注释嵌套注释_DIY注释的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中文字体临摹(中文字体linux)
- 下一篇: junit5和junit4_JUnit