分布式系统的一个重要问题就是分布式的事务,在没有分布式事务的前提下为了保证各个系统间数据的一致性比较简单易行的方法就是重试和补偿了。最近公司系统也遇到了这样的问题,远程调用超时或者消息消费失败之后造成了一些脏数据,为了给这些点统一加上重做机制首先就想到了Java的动态代理,如果稍微再能够灵活配置一点简单的做法就是加annotation。自己先写了一个简单的demo。
1。为了能够进行一些简单的配置化,定义了一个annotation。其中
- redoTimes:失败之后的重做次数。
- taskNameOnError:如果还是失败生成任务的名称。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface AutoRedo {
int redoTimes() default 1;
String taskNameOnError();
}
2。假如我们要动态代理的类和接口如下:(java本身的代理机制只支持接口的动态代理,如果要对类做动态代理可以使用cglib)。所以这个annotation一定要加在接口上,类上注解在代理上是不起作用的。
interface Subject {
@AutoRedo(redoTimes = 2, taskNameOnError = "xxRedoTask")
public void request();
}
class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject request()!");
}
}
3。代理的时候要做的事情:
class DynamicProxy implements InvocationHandler {
private Object obj;
public DynamicProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
int redoTimes = 0;
int failCnt = 0;
String taskNameOnError;
if (method.isAnnotationPresent(AutoRedo.class)) {
redoTimes = method.getAnnotation(AutoRedo.class).redoTimes();
taskNameOnError = method.getAnnotation(AutoRedo.class)
.taskNameOnError();
}
for (int i = 1; i <= redoTimes+1; i++) {
try {
method.invoke(this.obj, args);
break;
} catch (Exception e) {
failCnt++;
}
}
if (failCnt == redoTimes+1) {
// insert asynTask with name: taskNameOnError
}
return null;
}
}
4。最后写一个工厂来方便调用,因为java.lang.reflect.Proxy已经做了cache,保证同一个interface的proxy只动态生成一个。所以工厂就不做cache了,这样也不会出现持久带内存一直增长的问题。(无节制的生成动态class而产生的频发fullgc需要小心)
class RedoInterceptorFactory {
@SuppressWarnings("unchecked")
public static <T> T getInterceptedInstance(T target) {
InvocationHandler h = new DynamicProxy(target);
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), h);
}
}
5。真正的调用端
public static void main(String[] args) {
Subject realSubject = new RealSubject();
RedoInterceptorFactory.getInterceptedInstance(realSubject).request();
}
参考资料:
- http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/
- http://qa.taobao.com/?p=463
分享到:
相关推荐
- 动态代理:Java的`java.lang.reflect.Proxy`类可以创建动态代理对象,实现代理模式,用于AOP(面向切面编程)等。 使用反射时,需要注意以下几点: - 安全性:反射可以访问私有成员,可能导致安全问题,因此需要...
本文将深入探讨如何使用JavaPoet和Annotation来实现Android动态权限申请。 首先,让我们了解JavaPoet。JavaPoet是一个由Square公司开源的库,它允许我们以编程方式生成Java源代码。通过JavaPoet,我们可以创建类、...
Java动态代理是Java编程中的一种高级技术,它允许在运行时创建代理类,这些代理类可以作为原有类的代理,从而在调用原有方法时添加额外的功能或行为。在这个示例中,我们专注于如何利用注解来实现对JavaBean的动态...
将两者结合,我们可以在运行时通过动态代理检查方法参数是否为空,以此实现更灵活的代码验证和控制。 首先,让我们了解Java中的注解(Annotation)。注解是一种声明式的编程元素,它以`@`符号开头,后面跟着注解...
- 当定义一个注解时,实际上实现了`java.lang.annotation.Annotation`接口。注解类型的声明不允许有父接口或父类。 4. Retention策略: - `java.lang.annotation.Retention`:用于控制注解的生命周期,决定它在...
在Java编程语言中,Annotation(注解)是一种元数据,它提供了在编译时和运行时为代码添加信息的方式。注解是自Java 5版本引入的特性,它增强了代码的可读性和可维护性,同时也简化了某些编程任务。在本篇中,我们将...
在Java中,注解用于向编译器、JVM或第三方工具提供有关类、接口、方法、变量等的声明信息,帮助进行编译时检查、运行时处理或自动生成代码等任务。 注解的语法结构由`@`符号开头,后面跟着注解的类型,例如`@...
Java SSH项目是基于三个主要框架——Struts、Spring和Hibernate构建的企业级Web应用程序。这个项目中,Hibernate作为ORM(对象关系映射)工具被用来处理数据库操作,而使用了注解方式来配置Hibernate,这是一种更加...
- 拦截器是Struts2的核心组件之一,它们是基于Java的动态代理机制实现的。在Action调用前后,拦截器可以执行一系列预定义的任务,如日志记录、权限验证、数据校验等。 - 拦截器链是由多个拦截器按照特定顺序组成的...
在Java中,注解通常用于简化配置、验证输入、实现动态代理、生成代码以及进行编译时或运行时的检查等任务。 1. 注解类型: - 标准注解:Java标准库提供了一些预定义的注解,如@Override、@Deprecated、@ ...
Java 1.5 引入了一种新的元编程机制——注解(Annotation),极大地增强了代码的可读性和可维护性。注解是一种在代码中添加元数据的方式,它允许程序员在源代码上添加一些信息,这些信息可以被编译器或运行时环境...
### Java Annotation 概述与应用 #### 一、Java Annotation 的定义及作用 Java Annotation(注解)是自 Java 5.0 开始引入的一种语言元素,它为开发者提供了在代码中添加元数据的能力。简单来说,注解就像是对代码...
1. **预定义 Annotation**:JDK 内置了一些预定义的 Annotation,如 `@Override`、`@Deprecated` 和 `@ SuppressWarnings`,它们分别用于指示方法覆盖、标记过时和抑制警告。 2. **自定义 Annotation**:除了预定义...
在本篇文章中,我们将深入探讨基于Annotation的AOP实现,特别是动态代理的理念。 首先,了解什么是AOP。AOP的核心概念是“切面”(Aspect),它封装了跨越多个对象的行为或责任。切面可以包含通知(Advice)、切点...
Java annotation 什么是java annotation?annotation 的7种标注类型。nnotation提供了一条与程序元素关联任何信息或者任何元数据(metadata)的途径。从某些方面看,annotation就像修饰符一样被使用,并应用于包、...
在Java编程中,注解(Annotation)和反射(Reflection)是两个非常强大的工具,它们能够帮助我们实现更灵活、更具动态性的代码。本篇将详细探讨如何利用这两者来实现一个通用的数据库访问接口,以适应不同类型的...
Java预定义了多种注解,如@Override、@Deprecated、@ SuppressWarnings等,它们分别用于标记方法重写、提示弃用和抑制警告。此外,开发者还可以自定义注解以满足特定需求。 1.2 注解使用 注解可以在类、接口、方法...
Java 注解(Annotation)是Java语言提供的一种元编程机制,它允许程序员在源代码的各个元素(如类、方法、变量等)上添加信息。这些信息可以被编译器或运行时系统用来验证代码、执行特定操作或者提供额外的运行时...