标题静态代理与动态代理的区别
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式–代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。话不多说,直接上代码
静态代理
首先我们建一个公共proxy接口类
package com.honizon.proxy;
public interface personProxy {
//定义一个获取名字的方法
String getName();
}
再建一个类去实现它,这个类就是需要被代理的类。
package com.honizon.proxy.impl;
import com.honizon.proxy.personProxy;
public class studentProxy implements personProxy {
@Override
public String getName() {
System.out.println("张三");
return "被代理类";
}
}
接下就是关键代码,在创建一个类去实现personProxy,这样他就可做与studentProxy类一样的事情
package com.honizon.proxy.impl;
import com.honizon.proxy.personProxy;
public class teacherProxy implements personProxy {
//定义一个被代理的类
private studentProxy student;
public teacherProxy(personProxy student) {
this.student = (studentProxy)student;
}
//在teacherProxy类调用获取名字,并在之前叫老师好
public String getName(){
System.out.println("老师好");
student.getName();
return "代理类";
}
}
最后建一个测试类proxyTest,看如何使用代理模式:
package com.honizon.proxy;
import com.honizon.proxy.impl.studentProxy;
import com.honizon.proxy.impl.teacherProxy;
public class proxyTest {
public static void main(String[] args) {
//创建一个被代理的对象
personProxy student = new studentProxy();
//创建一个与代理对象,并把需要代理的对象放进去
personProxy teacher = new teacherProxy(student);
//获取名字
teacher.getName();
}
}
执行我们来看效果
在获取名字之前还叫了老师好,这就是代理模式好处,在执行原有事情下,还能做些别的,代理模式最主要的就是有一个公共接口(personProxy),一个具体的类(studentProxy),一个代理类(teacherProxy),代理类持有具体类的实例,代为执行具体类实例方法。上面说到,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。这里的间接性就是指不直接调用实际对象的方法,那么我们在代理过程中就可以加上一些其他用途
动态代理
动态代理相对静态代理跟灵活,跟方便,静态代理每一个需要被代理的类都需要创建代理类来管理,而动态代理是基于InvocationHandler类来实现,并不需要创建那么多的代理类,静态代理的代理是在运行之前就编译好的,而动态代理是在运行程序根据指令生成的,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法
- 代码
先定义公共接口类personProxy
package com.honizon.proxy;
public interface personProxy {
String getName();
}
接下创建一个实体类实现InvocationHandler类,这个类中持有一个被代理对象的实例target。InvocationHandler中有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法。,并在里面利用反射调用获取名字的方法,在方法之前打印执行了什么方法。
package com.honizon.Dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class personHandler<T> implements InvocationHandler {
T tager;
public personHandler(T tager) {
this.tager = tager;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理执行" + method.getName() + "方法");
Object object = method.invoke(tager, args);
if(object != null){
System.out.println("获取到" + object.toString() + "的名字");
}
return object;
}
}
接下写测试类
package com.honizon.proxy;
import com.honizon.Dynamic.personHandler;
import com.honizon.proxy.impl.studentProxy;
import com.honizon.proxy.impl.teacherProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class proxyTest {
public static void main(String[] args) {
//创建一个被代理的对象
personProxy student = new studentProxy();
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler stuHandler = new personHandler<personProxy>(student);
//动态生成代理对象,并将学生传给代理对象
personProxy teacher = (personProxy) Proxy.newProxyInstance(personProxy.class.getClassLoader(), new Class<?>[]{personProxy.class}, stuHandler);
teacher.getName();
}
}
看效果
Connected to the target VM, address: '127.0.0.1:64135', transport: 'socket'
Disconnected from the target VM, address: '127.0.0.1:64135', transport: 'socket'
代理执行getName方法
张三
获取到被代理类的名字
Process finished with exit code 0
- 总结
相对直接调用,代理模式的好处在于在执行方法之前做些其他处理,而动态代理的优势在于他的代理是有代码指令完成的,不需要手动去创建。而且每个方法在invoke里统一执行,方便管理。