JDK 从1.3开始提供的 Proxy 工具类, 以提供用代理的方式去执行某个接口的某些方法, 在Spring AOP的实现中就有应用;
JDK: 1.8
代码示例
1 . 需要被代理的接口
package com.test.reflect;
/**
* @author Hinsteny
* @Describtion
* @date 2016/12/2
* @copyright: 2016 All rights reserved.
*/
public interface Scholar {
String LOCAL = "CHIBA";
String searching(String theme);
default String infoLocal(){
return this.LOCAL;
}
}
2 . 需要被代理的实现类
package com.test.reflect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
/**
* @author Hinsteny
* @Describtion
* @date 2016/12/2
* @copyright: 2016 All rights reserved.
*/
public class ScholarImpl implements Scholar {
static final private Logger logger = LoggerFactory.getLogger(ScholarImpl.class);
public static String printTime(){
logger.info("Now time is {}", LocalDateTime.now().toString());
return "Time";
}
@Override
public String searching(String theme) {
logger.info("Scholar do search {}", theme);
return "success";
}
}
3 . 实现InvocationHandler接口, 这里是代理执行的地方, 可以加入自定义业务逻辑(比如日志记录, 权限拦截, 统计等)
package com.test.reflect.jdk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author Hinsteny
* @Describtion
* @date 2016/12/2
* @copyright: 2016 All rights reserved.
*/
public class MyHandler implements InvocationHandler {
static final private Logger logger = LoggerFactory.getLogger(MyHandler.class);
private Object object = null;
public MyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
logger.info("do something before method {}", method.getName());
Object ret = method.invoke(this.object, args);
logger.info("do something after method {}", method.getName());
return ret;
}
}
4 . 查看代理效果的测试用例, 及生成代理类的class文件
package com.test.reflect.jdk;
import com.test.reflect.Scholar;
import com.test.reflect.ScholarImpl;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;
/**
* @author Hinsteny
* @Describtion
* @date 2016/12/2
* @copyright: 2016 All rights reserved.
*/
public class JDKProxyTest {
static final private Logger logger = LoggerFactory.getLogger(JDKProxyTest.class);
@Test
public void testProxy(){
// 元对象(被代理对象)
ScholarImpl managerImpl = new ScholarImpl();
// 业务代理类
MyHandler securityHandler = new MyHandler(managerImpl);
// 获得代理类($Proxy0 extends Proxy implements Manager)的实例.
Scholar managerProxy = (Scholar) Proxy.newProxyInstance(JDKProxyTest.class.getClassLoader(), managerImpl.getClass().getInterfaces(), securityHandler);
logger.info("Scholar local is {}", managerProxy.LOCAL);
logger.info("Scholar default method do and result is {}", managerProxy.infoLocal());
String theme = "knowledge";
String result = managerProxy.searching(theme);
logger.info("result is {}", result);
}
@Test
public void testGetProxyClass_1(){
// 需要添加java命令执行时参数 [-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true]
// 然后生成的动态代理对象会在下面目录的子目录 [com\sun\proxy] 中, 命名是从 [$Proxy#.class](#从0开始依次加1递增)
System.out.println(System.getProperty("user.dir"));
testProxy();
// 可以去对应目录去查看生成的动态class类文件, 反编译出动态类的java代码
logger.info("Finish at here {}");
}
@Test
public void testGetProxyClass_2(){
// 获取代理类的字节码
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", ScholarImpl.class.getInterfaces());
// 写入文件
String path = "D://data/$Proxy1.class";
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5 . 反编译查看生成动态类源代码
package com.sun.proxy;
import com.test.reflect.*;
import java.lang.reflect.*;
public final class $Proxy20 extends Proxy implements Scholar
{
private static Method m1;
private static Method m2;
private static Method m4;
private static Method m3;
private static Method m0;
public $Proxy20(final InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final boolean equals(final Object o) {
try {
return (boolean)super.h.invoke(this, $Proxy20.m1, new Object[] { o });
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final String toString() {
try {
return (String)super.h.invoke(this, $Proxy20.m2, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final String infoLocal() {
try {
return (String)super.h.invoke(this, $Proxy20.m4, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final String searching(final String s) {
try {
return (String)super.h.invoke(this, $Proxy20.m3, new Object[] { s });
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final int hashCode() {
try {
return (int)super.h.invoke(this, $Proxy20.m0, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
static {
try {
$Proxy20.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
$Proxy20.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
$Proxy20.m4 = Class.forName("com.test.reflect.Scholar").getMethod("infoLocal", (Class<?>[])new Class[0]);
$Proxy20.m3 = Class.forName("com.test.reflect.Scholar").getMethod("searching", Class.forName("java.lang.String"));
$Proxy20.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
}
catch (NoSuchMethodException ex) {
throw new NoSuchMethodError(ex.getMessage());
}
catch (ClassNotFoundException ex2) {
throw new NoClassDefFoundError(ex2.getMessage());
}
}
}
注: