项目目录结构
项目下载
https://github.com/cbeann/Demoo/tree/master/async-demo
实践
pom
代码语言:javascript复制 <!-- https://mvnrepository.com/artifact/cglib/cglib -->
<!--cglib依赖-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
自定义标注注解
没有方法参数的注解成为标注注解
代码语言:javascript复制//Async注解
@Target(ElementType.METHOD)//方法注解
@Retention(RetentionPolicy.RUNTIME)//运行时注解
public @interface MyAsyncInterface {
}
自定义执行器
代码语言:javascript复制package com.imooc.demo.executor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.concurrent.FutureTask;
public class MyExecutor {
/*
动态代理的异步执行方法,参数就是 invoke(Object proxy, Method method, Object[] args)
*/
public static void submit(Object object, Method method, Object[] args) throws Exception {
//封装成callable接口
MyDyCallable myCallable = new MyDyCallable(object, method, args);
FutureTask futureTask = new FutureTask(myCallable);
//运行线程
new Thread(futureTask).start();
}
/*
cglib的异步执行方法intercept(Object object, Method method, Object[] args, MethodProxy proxy)
*/
public static void submit(Object object, Method method, Object[] args, MethodProxy proxy) throws Exception {
//封装成callable接口
MyCglibCallable myCglibCallable = new MyCglibCallable(object, method, args, proxy);
FutureTask futureTask = new FutureTask(myCglibCallable);
//运行线程
new Thread(futureTask).start();
}
}
实现动态代理的异步执行
IEmailService接口
代码语言:javascript复制public interface IEmailService {
public void sendEmail();
public void speak();
}
IEmailService接口实现类
其中带有MyAsyncInterface我们要使其成为异步方法
代码语言:javascript复制package com.imooc.demo.dyproxy;
import com.imooc.demo.myinterface.MyAsyncInterface;
public class EmailService implements IEmailService {
@MyAsyncInterface
@Override
public void sendEmail() {
System.out.println("开始发送email---------->睡10秒");
try {
//处理业务10毫秒
Thread.sleep(1000 * 2);
} catch (Exception e) {
}
System.out.println("结束发发送email<----------");
}
public void speak() {
System.out.println("-----EmailService------");
}
}
MyAsyncHandler (动态代理知识)
代码语言:javascript复制package com.imooc.demo.dyproxy;
import com.imooc.demo.myinterface.MyAsyncInterface;
import com.imooc.demo.executor.MyExecutor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyAsyncHandler implements InvocationHandler {
//目标对象
private Object target;
//传入代码目标对象
public MyAsyncHandler(Object object) {
this.target = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable, Exception {
//method参数是接口的方法,上面是不带@MyAsyncInterface的,我们一般是定义在接口实现类上,所以我们通过接口的method获取target(实现类)的方法,从而获取自定义注解信息
MyAsyncInterface annotation = target.getClass().getMethod(method.getName(), method.getParameterTypes()).getAnnotation(MyAsyncInterface.class);
if (null != annotation) {
//如果该方法有自定义异步注解,启动线程跑
MyExecutor.submit(target, method, args);
} else {
//如果该方法没有自定义异步注解,同步执行
Object invoke = method.invoke(target, args);
}
//如果有结果返回,如果没有就不返回
return null;
}
}
MyDyCallable:实现Callable接口(多线程知识)
目的:如果方法时异步,将参数传入callable,并且启动线程执行
代码语言:javascript复制package com.imooc.demo.executor;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
public class MyDyCallable implements Callable<Object> {
private Object target;
private Method method;
private Object[] args;
public MyDyCallable(Object object, Method method, Object[] args) {
this.target = object;
this.method = method;
this.args = args;
}
@Override
public Object call() throws Exception {
Object result = method.invoke(target, args);
return result;
}
}
ProxyStart:测试类
代码语言:javascript复制package com.imooc.app;
import com.imooc.demo.dyproxy.EmailService;
import com.imooc.demo.dyproxy.IEmailService;
import com.imooc.demo.dyproxy.MyAsyncHandler;
import java.lang.reflect.Proxy;
public class ProxyStart {
public static void main(String[] args) {
IEmailService emailService = new EmailService();
MyAsyncHandler asyncHandler = new MyAsyncHandler(emailService);
Class cls = emailService.getClass();
//创建动态代理对象
IEmailService newProxyInstance = (IEmailService) Proxy.newProxyInstance(
cls.getClassLoader(), cls.getInterfaces(), asyncHandler);
//此方法时异步
newProxyInstance.sendEmail();
//此方法时同步
newProxyInstance.speak();
// 执行结果如下:
// -----EmailService------ newProxyInstance.speak()方法
// 开始发送email---------->睡10秒 newProxyInstance.sendEmail();方法
// 结束发发送email<----------
}
}
实现cglib的异步执行
MQService
方法setMessage方法,我们使其成为异步方法
代码语言:javascript复制package com.imooc.demo.cglibproxy;
import com.imooc.demo.myinterface.MyAsyncInterface;
public class MQService {
@MyAsyncInterface
public void setMessage(String messgae) {
System.out.println("开始发送MQmessage--------->睡3秒");
try {
Thread.sleep(1000 * 3);
} catch (Exception e) {
}
System.out.println("结束发送MQmessage<-------------");
}
}
CGlibProxy (动态代理cglib知识)
代码语言:javascript复制package com.imooc.demo.cglibproxy;
import com.imooc.demo.executor.MyExecutor;
import com.imooc.demo.myinterface.MyAsyncInterface;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGlibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clz) {
enhancer.setSuperclass(clz);
enhancer.setCallback(this);
return enhancer.create();
}
/**
* @param object 目标类的实例
* @param method 目标方法的反射对象
* @param args 目标方法的参数
* @param proxy 代理类的实例
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if (method.getAnnotation(MyAsyncInterface.class) != null) {
MyExecutor.submit(object, method, args, proxy);
} else {
proxy.invokeSuper(object, args);
}
return null;
}
}
MyCglibCallable (多线程知识)
代码语言:javascript复制package com.imooc.demo.executor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
public class MyCglibCallable implements Callable {
private Object object;
private Method method;
private Object[] args;
private MethodProxy proxy;
//参数是intercept(Object object, Method method, Object[] args, MethodProxy proxy)
public MyCglibCallable(Object object, Method method, Object[] args, MethodProxy proxy) {
this.object = object;
this.args = args;
this.method = method;
this.proxy = proxy;
}
@Override
public Object call() {
try {
proxy.invokeSuper(object, args);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}
CGlibStart 测试类
代码语言:javascript复制package com.imooc.app;
import com.imooc.demo.cglibproxy.CGlibProxy;
import com.imooc.demo.cglibproxy.MQService;
public class CGlibStart {
public static void main(String[] args) {
// MQService mqService = new MQService();
// mqService.setMessage("123123");
CGlibProxy cGlibProxy = new CGlibProxy();
MQService proxy = (MQService) cGlibProxy.getProxy(MQService.class);
proxy.setMessage("123");
System.out.println("-----------------------");
// 执行结果
// ----------------------- System.out.println("-----------------------");
// 开始发送MQmessage--------->睡3秒 proxy.setMessage("123");
// 结束发送MQmessage<-------------
}
}
总结
1)需要了解动态代理、多线程知识
2)上面都是按照方法没有返回结果算的,实际情况下是很多是有结果的
3)多线程中Callable是有返回结果的