DIY注释

从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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/354562.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这款电脑升降桌美到我了

一直在寻觅一款集颜值与功能于一体的电脑升降桌&#xff0c;这款乐歌 E5 电动桌终于成功地满足了我的需求。有黑白两款颜色可选&#xff0c;但其中白色钢化玻璃版常适合用来作为白色系桌面的基础——四周圆角设计&#xff0c;再加上碳素钢的桌体框架&#xff0c;整体非常有质感…

spring boot集成mybatis+事务控制

一下代码为DEMO演示&#xff0c;采用注解的方式完成Spring boot和Mybatis的集成&#xff0c;并进行事物的控制 数据源的配置: 1 spring.datasource.urljdbc:mysql://localhost:3306/book 2 spring.datasource.usernameroot 3 spring.datasource.password 4 spring.datasource.d…

分享一个引起极度舒适的工作桌面

干净整洁的桌面或许不能带给你工作效率的提升&#xff0c;但一定会给你带来愉悦的心情。长期码字一定需要一个升降桌&#xff0c;可自由地调节高度&#xff0c;以保证舒适的坐姿和灵活的视角。另外坐久了&#xff0c;累了还能站立工作一会儿。有了外显之后&#xff0c;如果不需…

canvas绘制多边形

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>canvas绘制多边形</title> </head> <body> <canvas id"canvas" style"border: 1px solid darkcyan;" width…

ehcache rmi_EhCache复制:RMI与JGroups

ehcache rmi最近&#xff0c;我正在研究一种需要复制缓存的产品。 缓存提供程序已经确定-EhCache&#xff0c;剩下的就是有关传输的问题。 哪一个是最佳选择&#xff1f; 这里的最佳选择是指性能更好的选择。 仅在两个可用传输之间进行了性能评估-JGroups和RMI&#xff0c;对其…

Element Table 可以实现哪些常见的有用的功能

最近项目中频繁使用 table 功能&#xff0c;因为 UI 框架使用的又是 Element UI&#xff0c;于是总结下在 Element 下 el-table 组件使用技巧。1.行背景色table 组件提供了 row-style 属性&#xff0c;说明&#xff1a;行的 style 的回调方法&#xff0c;也可以使用一个固定的 …

从0开始 Java实习 黑白棋

黑白棋的设计 代码如下&#xff1a; import java.util.*; public class Chess{char[][] chess new char[16][16];public static void main(String args[]){ Scanner in new Scanner(System.in);Chess ch new Chess();ch.init(); ch.output();int tag 0;int nn 0;wh…

如果在这样的环境中写代码,会不会很高效

桌面环境分享系列又来了。我会把平时看到的好的桌面布置分享给大家&#xff0c;帮助大家在桌面整理和打造方面提供一些新的想法和创意。如何评价一个开发桌面的好坏&#xff0c;首先一定要清爽整洁&#xff0c;该有的家伙事儿一定要有。不是要看上去要有多高大上&#xff0c;重…

为什么选择SpringBoot?

使用Spring MSpring进行许可是一种非常流行的基于Java的框架&#xff0c;用于构建Web和企业应用程序。 与许多其他只关注一个领域的框架不同&#xff0c;Spring框架通过其投资组合项目提供了广泛的功能来满足现代业务需求。 Spring框架提供了以多种方式&#xff08;例如XML &a…

wamp2.5可用php5.6,局域网访问,多站点配置

1.用php5.6 直接下载个wamp3.0的&#xff0c;那里的php支持5.6&#xff0c;安装之后把php5.6的文件夹剪切到wamp2.5的放php的文件夹&#xff0c;然后wamp那里就有php5.6的选择了&#xff0c;选择后就可以用了 2.局域网访问 打开apache的配置文件&#xff0c;然后搜索Require lo…

Vue 页面如何监听用户预览时间

最近的业务中涉及到这样一个需求&#xff0c;在线培训的系统需要知道用户对某个在线预览的页面追踪用户的预览时长。初步我们首先想到借助 Vue 页面的生命周期函数 mounted 和 destroyed&#xff0c;分别在其中加入开始计时和清除计时的逻辑&#xff0c;通过后台的接口上报对应…

一个追求高效的学习者手机里装有哪些APP?(转)

转载&#xff1a;http://www.jianshu.com/p/f568c8d8b6bb 1、录音软件-Recordium 参加活动&#xff0c;如果不想错过活动现场的经常片段&#xff0c;速记又来不及&#xff0c;那就选择录音吧。小六之前都使用录音笔&#xff0c;但是自从有了这个APP之后&#xff0c;在开会&…

spring social_Spring Social入门

spring social像我一样&#xff0c;无论是添加简单的Facebook“赞”按钮&#xff0c;一大堆“共享”按钮还是显示时间轴信息&#xff0c;您都不会注意到当前对应用程序“社交化”的热衷。 每个人都在做这件事&#xff0c;包括Spring的家伙&#xff0c;事实上&#xff0c;他们提…

Vue 页面如何利用生命周期函数监听用户预览时长

最近的业务中涉及到这样一个需求&#xff0c;在线培训的系统需要知道用户对某个在线预览的页面追踪用户的预览时长。初步我们首先想到借助 Vue 页面的生命周期函数 mounted 和 destroyed&#xff0c;分别在其中加入开始计时和清除计时的逻辑&#xff0c;通过后台的接口上报对应…

iOS 11 UICollectionView顶部出现白色间隔的问题

iOS11 UICollectionView顶到屏幕顶端会出现一个20高度的白色间隔&#xff0c;是由于UICollectionView的自动调整功能为状态栏留出的位置 只需在创建UICollectionView时加入如下代码关闭自动调整&#xff1a; 该属性是iOS11新加入的&#xff0c;所以一定要在前面加上判断&#x…

项目中的富文本编辑器该如何选择?

项目中经常需要用到富文本编辑器的时候&#xff0c;而常见的富文本编辑器都有哪些&#xff1f;该如何选择&#xff1f; 先看看市面上都有哪些可用的富文本编辑器&#xff1a; TinyMCE&#xff08;插件式的&#xff0c;支持 Vue&#xff0c;React&#xff0c;Angular 框架&…

根据自己的博客数据统计国内IT人群

装上百度统计有一段时间了&#xff0c;今天突然找出报表看看&#xff0c;发现一个很有意思的事情。访问来源TOP5依次是&#xff1a;北京&#xff0c;上海&#xff0c;深圳&#xff0c;杭州&#xff0c;广州 虽然大部分文章都是当时特别白的时候记录下来的遇到过的问题&#xff…

Vue刷新页面有哪几种方式

在Vue项目中&#xff0c;刷新当前页除了 window.reload()&#xff0c;你还能想到什么办法&#xff1f;而且这种办法会重新加载资源出现短暂的空白页面。体验不是很好。 在某个详情页面的时候&#xff0c;我们经常需要通过路由中的详情 id 去获取内容&#xff0c;当我们在不同的…

java web服务_将Java服务公开为Web服务

java web服务本教程解决了开发人员面临的最实际的情况。 大多数时候&#xff0c;我们可能需要将某些现有服务公开为Web服务。 在项目生命周期的不同阶段可能会遇到这种情况。 如果这是初始阶段&#xff0c;那么您几乎是安全的&#xff0c;您可以为此做好充分的准备。 但是&…

python文件打开方式详解——a、a+、r+、w+区别

第一步 排除文件打开方式错误&#xff1a;r只读&#xff0c;r读写&#xff0c;不创建w新建只写&#xff0c;w新建读写&#xff0c;二者都会将文件内容清零&#xff08;以w方式打开&#xff0c;不能读出。w可读写&#xff09;**w与r区别&#xff1a;r&#xff1a;可读可写&#…