读书人

凭借Javassist实现将方法转为异步执行

发布时间: 2012-12-26 14:39:28 作者: rapoo

借助Javassist实现将方法转为异步执行
找点事情做,写点代码练练手。实现一个简单的功能:将标注了@Async注解的实例方法调用时自动异步执行。
Spring3中已支持此功能, 如:

   @Service   public class MailServiceImpl implements MailService{    @Async    public void send(Mail mail){      //在此实现发送email逻辑      //异步执行的    }   }

至于Spring对它的实现原理在此就不罗嗦了, 反正离不开AOP、动态代理、多线程等技术。Guice 也有AOP支持, 要实现此功能,需要自己写点代码了。

现在我来借助Javassist手工编写个简单山寨版。

直接上源码吧,加了点点注释:
1 注解Async源码(Async.java)
import static java.lang.annotation.RetentionPolicy.RUNTIME;import static java.lang.annotation.ElementType.METHOD;import java.lang.annotation.Retention;import java.lang.annotation.Target;/** * 异步执行的方法注解. * */@Target(METHOD) @Retention(RUNTIME)public @interface Async {}


2 实现和测试代码(Main.java)
import java.lang.reflect.Method;import java.util.logging.Level;import java.util.logging.Logger;import javassist.util.proxy.MethodFilter;import javassist.util.proxy.MethodHandler;import javassist.util.proxy.ProxyFactory;import javassist.util.proxy.ProxyObject;    public class Main {public static void main(String[] args) throws InstantiationException, IllegalAccessException {long s = System.currentTimeMillis();new Main().asynMethod();System.out.println((System.currentTimeMillis() - s));Main main = getManagedBean(Main.class, new AsynMethodHandler());s = System.currentTimeMillis();main.asynMethod();System.out.println((System.currentTimeMillis() - s));  //输出的值远远小于2000哦, 达到异步目的}    /**     * 模拟从"容器"获取管理的Bean.     */public static <T> T getManagedBean(Class<T> type, TheMethodHandler mh) {ProxyFactory f = new ProxyFactory();f.setSuperclass(type);f.setFilter(mh.getMethodFilter());Class c = f.createClass(); //创建代理类T main = null;try {main = (T) c.newInstance(); //使用代理类创建实例((ProxyObject) main).setHandler(mh.getMethodHandler()); //设置方法拦截器return main;} catch (Exception ex) {Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);}return main;}    /**     * 想要异步执行的方法, 标注了@Async     */@Asyncpublic void asynMethod() {try {Thread.sleep(2000);System.out.println("hello");} catch (Exception ex) {Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);}}public static interface TheMethodHandler {public MethodFilter getMethodFilter();public MethodHandler getMethodHandler();}static class AsynMethodHandler implements TheMethodHandler {public MethodFilter getMethodFilter() {return new MethodFilter() {public boolean isHandled(Method m) {boolean isAsyncMethod = m.isAnnotationPresent(Async.class);//拦截标注为@Async的方法(并排除finalize方法)return !m.getName().equals("finalize") && isAsyncMethod;}};}public MethodHandler getMethodHandler() {return new MethodHandler() {public Object invoke(final Object self, Method m, final Method proceed,final Object[] args) throws Throwable {    //用new Thread的方式简单实现//TODO:用JUC替换(new Thread() {@Overridepublic void run() {try {proceed.invoke(self, args);} catch (Exception e) {throw new RuntimeException(e);}}}).start();return null; //TODO: 返回Feture?}};}}}




读书人网 >编程

热点推荐