借助Javassist实现将方法转为异步执行
找点事情做,写点代码练练手。实现一个简单的功能:将标注了@Async注解的实例方法调用时自动异步执行。
Spring3中已支持此功能, 如:
@Service public class MailServiceImpl implements MailService{ @Async public void send(Mail mail){ //在此实现发送email逻辑 //异步执行的 } }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 {}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?}};}}}