注释嵌套注释

从Java 5开始,Java中出现了注释。 我想做一个自己的注释,只是为了看看需要什么。 但是,我发现它们只是接口。

有擦

接口后面没有牙。 必须执行一些代码。 我认为这是橡胶行之有效的方法,我真的找到了解决方法。

首先,我需要一个目标

我选择了一个最近的热门话题:缓存。 我不想实现JSR 109(JCache),但也不想做典型的“ Hello World”。 我选择实现两个注释,一个注释不带任何参数,另一个注释不带参数。 我还需要一个缓存提供程序。 如果我要这样做的话,还可以将真正的缓存库加入其中。 它还遵循我的设计理念,即使用产品/库来达成目标,而不是将所有内容都进行家庭纺。 经过仔细考虑,我选择了hazelcast作为我的缓存引擎。 它是市场上最快的,而且是免费的。

更多决定

在选择了目标之后,我仍然需要找出如何在它们后面扎牙的方法。 经过一番挖掘,我发现了两种方法:

反射

几乎每次使用反射时,我都会为编写这么笨拙的代码感到遗憾。 另外,要按照我想要的方式进行操作,我必须创建自己的框架。 听起来两个注解的工作量很大。

面向方面的编程(AOP)

这非常适合我想做的事。 AOP致力于将样板代码减少到一个地方。 这将很方便并且与缓存紧密结合,因为缓存可分为以下步骤:

  1. 检查此情况是否之前已完成。
  2. 如果是这样的话:
    1. 检索存储的结果
  3. 如果不:
    1. 运行功能
    2. 存储结果
  4. 返回结果

也许这过于简单,但总的来说是正确的。 就像所有事物一样,细节决定成败。

同时,回到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注释相关推荐

  1. 注释嵌套注释_注释,无处不在的注释

    注释嵌套注释 十年前的2004年 , Java 1.5开始提供注释. 很难想象没有此功能的代码. 实际上,首先引入了注释,以减轻开发人员编写繁琐的样板代码的痛苦,并使代码更具可读性. 考虑一下J2EE ...

  2. 注释嵌套注释_注释梦Night

    注释嵌套注释 @XmlElementWrapper(name="orders") @XmlJavaTypeAdapter(OrderJaxbAdapter.class) @XmlE ...

  3. java 编译 注释_Java编译、注释、常量简介

    java程序运行: .java文件:源文件 javac 字节码文件 java .java文件 --------> .class文件 --------> 结果 编译 运行 1.编译源文件: ...

  4. c语言表示注释,c语言中注释的位置

    匿名用户 1级 2011-10-21 回答 1 注释的原则和目的注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确.易懂.简洁.通过对函数或过程.变量.结 ...

  5. java注释和注解_注释注解JAVA注解

    发一下牢骚和主题无关: package anno; import java.lang.annotation.Retention; import java.lang.annotation.Retenti ...

  6. c语言注释的作用文百,C语言注释-C语言行注释-C语言注释块注释-嗨客网

    C语言注释教程 用于注解说明解释程序的文字就是注释,注释提高了代码的阅读性.同时,注释也是一个程序员必须要具有的良好编程习惯.我们应该首先将自己的思想通过注释先整理出来,再用代码去体现. 在 C语言注 ...

  7. Spring2.5注释驱动与基于注释的MVC

    写在前面: 好长时间没有写博客了,主要是最近一直忙于工作上面的事情没有研究什么新的东西,也没有什么写的,最近应一个朋友的邀请一起开发一套教材,我才有开始对Spring研究起来,今天把写的其中一部分贴出 ...

  8. java注释详解--javadoc注释

    一. Java注释分类 // 注释一行  /* ...... */ 注释若干行  /** ...... */ 注释若干行,并写入 javadoc 文档  通常这种注释的多行写法如下:  /**  * ...

  9. java的注释规范_Java代码注释规范

    1,单行(单行)-简短说明: ///... 单行注释: 代码中的单行注释. 最好在注释前有一个空行,并在其后加上与代码相同的缩进级别. 如果无法完成一行,则应使用块注释. 评论格式: 在行首注释: 在 ...

最新文章

  1. 用最新NLP库Flair做文本分类
  2. python模块--BeautifulSoup4 和 lxml
  3. java 国家名称排序,我有一个国家名单。我想按字母顺序对它进行排序,除了两个我想放在第一位的国家...
  4. linux查看磁盘io最多的进程,Linux 查看磁盘IO并找出占用IO读写很高的进程,磁盘占用很高...
  5. 易筋SpringBoot 2.1 | 第九篇:SpringBoot使用Redis内存数据库
  6. 重庆大学计算机软件,重庆大学计算机辅助设计制造软件采购.DOC
  7. 小巧票据打印软件免费下载
  8. dnastar拼接反向互补序列_DNAstar使用说明
  9. 冯乐乐之三,SHADERLAB入门
  10. HP如何装linux系统启动顺序,linux几种系统的启动顺序
  11. 2021-04-09
  12. HashMap底层扩容机制是2倍的原理
  13. 一文带你深入理解【Java基础】· 枚举类
  14. [CSAW‘22] 世界这么大
  15. scp向阿里云服务器上传文件
  16. 725 数模 空气污染问题研究 (15 五一 B)
  17. 离职通知邮件主题写什么好_“辞职”发邮件标题怎么写?
  18. 【1066】满足条件的数累加
  19. 在不同的paste网站上搜索泄漏的凭据Scavenger
  20. 仓库管理软件(WMS)免费版哪个好用?

热门文章

  1. P5072-[Ynoi2015]盼君勿忘【莫队,根号分治】
  2. 【做题记录】 [JLOI2011]不等式组
  3. M-SOLUTIONS Programming Contest 2020总结
  4. 初一模拟赛总结(2019.6.1)
  5. 【树形DP】没有上司的晚会 (ssl 1607)
  6. [BZOJ1095][ZJOI2007]捉迷藏 Query on a tree IV(树链剖分)
  7. Problem H Rock Paper Scissors,FFT
  8. Java 平台调试架构JPDA
  9. Hadoop生态Zookeeper安装
  10. Js如何判断undefined和null