public interface Person {
String searchHouse();
}
复制代码
public class MasterProxy implements Person {
private Person person;
public MasterProxy(Person person) {
this.person = person;
}
@Override
public String searchHouse() {
System.out.println("我是链家,我帮别人找房子..");
//第一个参数是target,也就是被代理类的对象;第二个参数是方法中的参数
String msg = person.searchHouse();
System.out.println("------------------------");
System.out.println("| | |");
System.out.println("| | |");
System.out.println("| | |");
System.out.println("|------- ------- -----");
System.out.println(" |");
System.out.println("|----------------------|");
System.out.println("我是链家,已经找到了..");
return msg;
}
}
复制代码
public class ProxyTest {
@Test
public void testJDKObject() {
Person person = new Master();
MasterProxy masterProxy = new MasterProxy(person);
String sb = masterProxy.searchHouse();
System.out.println(sb);
}
}
复制代码
缺点:java
public class Master implements Person{
@Override
public String searchHouse() {
System.out.println("我须要找一个整租两室一厅的房子");
return "done";
}
public static String pay() {
System.out.println("我支付了");
return "我支付了";
}
public final String sign() {
System.out.println("我签约了");
return "我签约了";
}
}
复制代码
JDK缓存
/** * 代理对象,不须要实现接口 * * 代理对象不须要实现接口,可是目标对象必定要实现接口,不然不能用动态代理 * @param <T> */
public class HomeLineJDK<T> implements InvocationHandler {
private Person target;
public T createProxyInstance(Person target){
this.target = target;
Class clazz = target.getClass();
//指定当前目标对象使用类加载器,获取加载器的方法是固定的
//目标对象实现的接口的类型,使用泛型方式确认类型
//事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法做为参数传入
T obj = (T)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
// new ProxyClass().getClazz("jdkObject");
return obj;
}
public T createProxyInstance(Class clazz){
T obj = (T)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
new ProxyClass().getClazz("jdkClass");
return obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//System.out.println("我是链家,我帮别人找房子..");
//第一个参数是target,也就是被代理类的对象;第二个参数是方法中的参数
Object msg = method.invoke(target, args);
System.out.println("我是链家,已经找到了..");
return msg;
}
}
复制代码
cglibide
/** * Cglib代理,也叫做子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展. */
public class HomeLineCglib implements MethodInterceptor {
private Object target;
public <T> T createProxyInstance(T targetObject){
this.target = targetObject; //给业务对象赋值
Enhancer enhancer = new Enhancer(); //建立增强器,用来建立动态代理类 也就是cglib中的一个class generator
enhancer.setSuperclass(this.target.getClass()); //为增强器指定要代理的业务类(即:为下面生成的代理类指定父类)
//设置回调:对于代理类上全部方法的调用,都会调用CallBack,而Callback则须要实现intercept()方法进行拦
enhancer.setCallback(this);
// 建立动态代理类对象并返回
T o = (T)enhancer.create();
// new ProxyClass().getCglibClazz(enhancer);
return o;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("我是链家,我帮别人找房子..");
//第一个参数是target,也就是被代理类的对象;第二个参数是方法中的参数
Object msg = methodProxy.invoke(this.target, objects);
System.out.println("我是链家,已经找完了..");
return msg;
}
}
复制代码
测试:性能
public class InvacationTest {
@Test
public void testJDKObject() {
Person person = new HomeLineJDK<Person>().createProxyInstance(new Master());
String sb = person.searchHouse();
// System.out.println(sb);
}
@Test
public void testJDKCLass() {
Person person1 = new HomeLineJDK<Person>().createProxyInstance(Master.class);
String sb1 = person1.searchHouse();
System.out.println(sb1);
}
@Test
public void testCglib() {
Master master = new Master();
master = new HomeLineCglib().createProxyInstance(master);
master.searchHouse();
}
@Test
public void testStaticCglib() {
Master master = new Master();
master = new HomeLineCglib().createProxyInstance(master);
master.pay();
}
@Test
public void testFinalCglib() {
Master master = new Master();
master = new HomeLineCglib().createProxyInstance(master);
master.sign();
}
}
复制代码
咱们能够$Proxy0获取到代理对象的class,反编译出生成的代理类测试
public class ProxyClass {
//获取到jdk代理对象的class
public void getClazz(String fileName){
String path = "D://"+fileName+".class";
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0",Master.class.getInterfaces());
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//获取到cglib对应的class
public void getCglibClazz(Enhancer enhancer){
String path = "D://cglib.class";
byte[] classFile = new byte[0];
try {
classFile = enhancer.getStrategy().generate(enhancer);
} catch (Exception e) {
e.printStackTrace();
}
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
复制代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import services.proxy.Person;
public final class $Proxy0 extends Proxy implements Person {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String searchHouse() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("services.proxy.Person").getMethod("searchHouse");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
复制代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import services.proxy.Person;
public final class $Proxy0 extends Proxy implements Person {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String searchHouse() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("services.proxy.Person").getMethod("searchHouse");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
复制代码
package services.proxy;
import org.junit.Test;
public class ProxyPerofrmanceTest {
@Test
public void testTime(){
testCglibCreateTime(10000);
testJdkCreateTime(10000);
System.out.println("-------------------");
testCglibExecuteTime(10);
testCglibExecuteTime(100);
testCglibExecuteTime(1000);
testCglibExecuteTime(10000);
testCglibExecuteTime(100000);
testCglibExecuteTime(1000000);
testCglibExecuteTime(10000000);
System.out.println("-------------------");
System.out.println("-------------------");
testJdkExecuteTime(10);
testJdkExecuteTime(100);
testJdkExecuteTime(1000);
testJdkExecuteTime(10000);
testJdkExecuteTime(100000);
testJdkExecuteTime(1000000);
testJdkExecuteTime(10000000);
}
public void testJdkExecuteTime(int times){
Person person = new HomeLineJDK<Person>().createProxyInstance(new Master());
long jdks = System.currentTimeMillis();
for (int i = 0;i<times;i++){
person.searchHouse();
}
long jdke = System.currentTimeMillis();
System.out.println("jdk"+times+"次执行方法到处理时间:"+(jdke-jdks));
}
public void testJdkCreateTime(int times){
long jdks = System.currentTimeMillis();
for (int i = 0;i<times;i++){
Person person = new HomeLineJDK<Person>().createProxyInstance(new Master());
}
long jdke = System.currentTimeMillis();
System.out.println("jkd建立代理对象"+times+"次处理时间:"+(jdke-jdks));
}
}
复制代码
jdk和cglib第一次建立对象会将对象缓存,因此咱们先建立一次去掉建立对象时间this
jdk | cglib |
---|---|
2 ms | 228 ms |
接下来咱们看执行对应方法的耗时spa
次数 | jdk | cglib |
---|---|---|
10 | 0 | 17 |
100 | 1 | 0 |
1000 | 0 | 1 |
10000 | 2 | 4 |
100000 | 5 | 4 |
1000000 | 13 | 9 |
10000000 | 94 | 44 |
能够看到在建立对象并缓存到内存中的时候,cglib耗时比较jdk严重。可是在正直的执行过程当中咱们能够看到开始的时候jdk的性能优于cglib当达到必定调用量的时候cglib的性能较jdk要好。代理