1.java动态代理出现的前因
众所周知,java是一个混合型语言,既是编译型又是解释型语言。.java文件通过编译器编译生成.clss字节码文件,在安装有JVM平台上解释运行.class文件。
所以java的语言特点就是,程序员写出来.java类->.class->运行,一旦程序代码类提交后编译成.class文件,就不能修改。
动态代理就是为了解决不能扩展修改的问题。学习动态代理前先理解代理的概念。
2.代理类-代理模式
代理模式是常用的设计模式之一,特征是代理类和被代理类有同一个接口类 。
代理模式提供了访问实际对象的中间层,通过调用代理类访问被代理类,例子来源于https://www.cnblogs.com/gonjan-blog/p/6685611.html。
3.静态代理
静态代理:程序员写的代理类或者特定的工具自动生成的源代码,在程序编译成.class文件后不能对其修改。
//接口
public interface Person {
//静态代理类需要先有接口
void giveMoney();
}
//被代理类,也是真正访问的类,和代理类一样,只实现同一个接口
public class Student implements Person {
private String name;
public Student(String name) {
super();
this.name = name;
}
@Override
public void giveMoney() {
// TODO Auto-generated method stub
System.out.println(name+"上交班费50元");
}
}
//代理类,和被代理类一样,只实现同一个接口
public class StudentsProxy implements Person {
Student stu;
public StudentsProxy(Person stu) {
if(stu.getClass()==Student.class) {
this.stu = (Student) stu;
}
}
@Override
public void giveMoney() {
// TODO Auto-generated method stub
//预处理或者扩展的方法
beforeMethod();
//代理类中,闯将被代理类对象后,调用被代理类的方法
stu.giveMoney();
}
//原来实现接口还能在实现接口的类里添加其他方法啊
void beforeMethod(){
System.out.println("无java经验找不着工作?");
}
}
import staticproxy.Person;
import staticproxy.Student;
import staticproxy.StudentsProxy;
public class StaticProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建被代理的对象,多态的扩展
Person student=new Student("皮皮");
//创建代理对象
Person studentProxy= new StudentsProxy(student);
studentProxy.giveMoney();
}
}
4.动态代理
动态代理是为了解决系统在运行时不能修改扩展的问题,在运行的状态下利用java反射机制动态生成 比如,下午完整的例子。
第一步,创建代理模式的接口Person
第二步,创建核心类,也就是被代理类Studentd
第三步,实现InvocationHandler 接口类创建StuInvocationHandler
第四步,调用过程中,创建一个代理对象stuProxy 来代替zhangsan,然后使用proxy类动态创建代理类。
//接口,代理模式都需要的接口
public interface Person {
//静态代理类需要先有接口
void giveMoney();
}
//创建要被代理的类
import staticproxy.Person;
public class Studentd implements Person {
String name;
public Studentd(String name) {
// TODO Auto-generated constructor stub
this.name = name;
}
@Override
public void giveMoney() {
// TODO Auto-generated method stub
try {
Thread.sleep(5000);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
System.out.println(name+"上交班费50元");
}
}
package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class StuInvocationHandler implements InvocationHandler {
//target是StuInvocationHandler所持有的被代理对象
Object target;
public StuInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable {
// TODO Auto-generated method stub
System.out.println("代理执行"+method.getName()+"方法");
//拓展的方法
//MonitorUntil
MonitorUntil.start();
Object result= method.invoke(target, arg2);
MonitorUntil.finish(method.getName());
return result;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import dynamicproxy.StuInvocationHandler;
import dynamicproxy.Studentd;
import staticproxy.Person;
public class DynamicProxyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建被代理的实例对象
Person zhangsan = new Studentd("皮皮");
//创建与代理对象相关联的InvocationHandler
InvocationHandler stuHandler= new StuInvocationHandler(zhangsan);
/*
* Person:自创接口类
*
* stuHandler:自创InvocationHandler
*
* 创建一个代理对象stuProxy 来代替zhangsan,代理对象的每个方法都会替换执行 StuInvocationHandler 中的方法
* Proxy提供了用于创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
* * */
Person stuProxy =(Person) Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[] {Person.class} , stuHandler);
stuProxy.giveMoney();
}
}
结果是:
5.动态代理和静态代理
当我们应用时jdk动态代理和静态代理区别在哪儿?
动态代理 | 静态代理 |
---|---|
1 jdk动态代理是在程序运行时,通过java的反射机制动态创建代理类,无需程序员手动编写它的代理类。 2 jdk动态代理一次可代理同一个接口下多个实现类。 3 jdk动态代理在运行前,不知道它所代理什么类。 | 1 代理类由程序员手动创建或者由特定工具自动生成源码,对源码编译后,在运行前就已经有.class代码。 2 静态代理只能代理一个类。 3 静态代理事先知道要代理哪个类 |