public class JavaSist02 {
/**
* JDK 动态代理 与 Cglib 动态代理
* 1: JDK 动态代理是利用 java 反射机制与JDK自身 class 生成 。 在调用本身方法前调用invokeHandler来处理
* 2: CGlib 动态代理则是利用 asm 开源包。对代理的类的 class 文件加载进来 。通过修改其字节码生成子类来处理
*
* 如果目标对象实现了接口,默认使用 JDK代理 来实现 AOP
* 如果目标对象实现了接口,可强制使用CGlib接口来实现AOP
*
* 如何强制使用CGLIB实现AOP?
* (1)添加CGLIB库,SPRING_HOME/cglib/*.jar
* (2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
*
* JDK 动态代理与 CGlib 的区别
* (1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
* (2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
*/
public static void main(String[] args) throws Exception {
// 利用 sist 实现动态代理
crateProxy(TestService.class, (methodName, args13) -> {
System.out.println("hello:" + args13[0]) ;
return null;
}).sayHello("上卿");
crateProxy(TestService.class, (methodName, args12) -> {
System.out.println("hello:" + args12[0] + "年龄" + args12[1]) ;
return null;
}).sayHello("上卿", 18);
String sayHello = crateProxy(TestService.class, (methodName, args1) -> String.format("姓名:%s,性别:%s",args1)).sayHello("上卿", "男");
System.out.println(sayHello);
}
static int count = 0;
public static <T> T crateProxy(Class<T> interfaceClazz , InvocationHeadler headler) throws Exception{
ClassPool pool = new ClassPool();
pool.appendSystemPath();
// 防止类名重复
CtClass proxy = pool.makeClass("proxy" + count++);
proxy.addInterface(pool.get(interfaceClazz.getName()));
// 添加属性
CtField make = CtField.make("public com.shangqing.api.proxy.JavaSist02.InvocationHeadler headler=null;", proxy);
proxy.addField(make);
String result = "return ($r)this.headler.invoke(\"$s\",$args);";
String voidResult = "this.headler.invoke(\"$s\",$args);";
for (Method method : interfaceClazz.getMethods()) {
// 返回值类型,方法名称,参数,异常,实现类
CtClass returnType = pool.get(method.getReturnType().getName());
String methodName = method.getName();
CtClass[] parameters = toCtClass(pool, method.getParameterTypes());
CtClass[] errors = toCtClass(pool, method.getExceptionTypes());
String srcImpl;
if (method.getReturnType().equals(Void.class)) {
srcImpl = voidResult;
} else {
srcImpl = result;
}
CtMethod ctMethod = CtNewMethod.make(returnType, methodName, parameters, errors, srcImpl, proxy);
proxy.addMethod(ctMethod);
}
// toClass 同时会将 类加载到 classloader 中
Class toClass = pool.toClass(proxy);
T t = (T) toClass.newInstance();
toClass.getField("headler").set(t,headler);
return t;
}
private static CtClass[] toCtClass(ClassPool pool , Class[] classes){
return Arrays.stream(classes).map(c -> {
try {
return pool.get(c.getName());
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
}).toArray(CtClass[]::new);
}
public interface InvocationHeadler{
Object invoke(String methodName , Object[] args);
}
public interface TestService{
void sayHello(String name);
void sayHello(String name,int age);
String sayHello(String name,String sex);
}
}
JAVA-动态代理篇
最新推荐文章于 2024-10-06 20:16:20 发布