1、静态代理与动态代理的区别
-
静态代理就是在程序运行前就已经存在代理类的字节码文件、代理类和原始类的关系在运行前就已经确定。
-
而动态代理采用反射技术,在运行时才确定代理哪个方法。
动态代理的好处在哪儿?举个简单的例子
2、静态代理
- 1.首先写一个Human这个接口,模拟人类的行为:吃饭,睡觉,学习,工作
/**
* @author XiangYida
* @version 2019/4/7 14:43
* 模拟人的行为
*/
public interface Human {
//吃饭
public void eat();
//睡觉
public void sleep();
//学习
public void study();
//工作
public void work();
}
- 2.写一个Student类,实现这个接口,实现里面的方法。
/**
* @author XiangYida
* @version 2019/4/7 14:45
* 学生类
*/
public class Student implements Human {
@Override
public void eat() {
System.out.println("I am eating");
Thread.sleep(200);
}
@Override
public void sleep() {
System.out.println("I am sleeping");
Thread.sleep(2000);
}
@Override
public void study() {
System.out.println("I am studying");
Thread.sleep(1000);
}
@Override
public void work() {
System.out.println("I am working");
Thread.sleep(1000);
}
}
- 3.然后是代理类,来记录每个行为的时间
/**
* @author XiangYida
* @version 2019/4/7 14:48
*/
public class MyProxy {
Human student=new Student();
public void eat(){
long l1=System.currentTimeMillis();
student.eat();
System.out.println("===============your eat time is "+(System.currentTimeMillis()-l1));
}
public void sleep() {
long l1=System.currentTimeMillis();
student.sleep();
System.out.println("===============your sleep time is "+(System.currentTimeMillis()-l1));
}
public void study() {
long l1=System.currentTimeMillis();
student.study();
System.out.println("===============your study time is "+(System.currentTimeMillis()-l1));
}
public void work() {
long l1=System.currentTimeMillis();
student.work();
System.out.println("===============your work time is "+(System.currentTimeMillis()-l1));
}
}
- 4.测试
/**
* @author XiangYida
* @version 2019/4/7 14:52
*/
public class Test {
public static void main(String[] args) {
MyProxy proxy=new MyProxy();
proxy.eat();
proxy.sleep();
proxy.work();
proxy.study();
}
}
- 5.结果
I am eating
===============your eat time is 201
I am sleeping
===============your sleep time is 2001
I am working
===============your work time is 1002
I am studying
===============your study time is 1000
-
为什么要用静态代理呢:代理保证了业务类只需关注逻辑本身,代理对象的一个接口只服务于一种类型的对象说通俗一点就是我只管我要做的事情,其他的事儿由代理来完成,比如你要去旅游,你只管去玩,其他订票日程安排啥的都有代理公司来帮你完成。
-
那么,静态代理的缺点是什么呢。前面已经说过了,在程序运行前就已经存在代理类的字节码文件、代理类和原始类的关系在运行前就已经确定。这里模拟的人的行为只有四个,那假如有一万个行为呢,那是不是得在代理类中写一万个代理的方法。还有加入需要代理的对象不是Student了,而是Teacher了。是不是还得再来代理这个对象的行为?
所以就引出了动态代理,使用反射技术,在程序运行时根据需要来确定代理相应的对象方法
3、动态代理
我们还是用Human这个例子,先上代码
Human接口以及Student类跟前面一样,这里就不写了。
- 代理类(需要实现InvocationHandler接口,并重写invok方法)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author XiangYida
* @version 2019/4/7 15:18
*/
public class MyProxy implements InvocationHandler {
private Object target=null;
//绑定需要代理的对象
public Object bind(Object target){
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//实现具体逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long l1=System.currentTimeMillis();
Object obj=method.invoke(target,args);
System.out.println("===============your sleep time is "+(System.currentTimeMillis()-l1));
return obj;
}
}
- 测试
public class Test {
public static void main(String[] args) {
MyProxy myProxy=new MyProxy();
Human student=(Human)myProxy.bind(new Student());
student.eat();
student.study();
student.sleep();
student.work();
}
}
- 运行结果
I am eating
===============your sleep time is 205
I am studying
===============your sleep time is 1001
I am sleeping
===============your sleep time is 2001
I am working
===============your sleep time is 1000
- 现在我要添加代理一个Teacher类
/**
* @author XiangYida
* @version 2019/4/7 15:35
*/
public class Teacher implements Human {
@Override
public void eat() {
System.out.println("I am a teacher~~~");
System.out.println("I am eating");
Thread.sleep(200);
}
@Override
public void sleep() {
System.out.println("I am a teacher~~~");
System.out.println("I am sleeping");
Thread.sleep(2000);
}
@Override
public void study() {
System.out.println("I am a teacher~~~");
System.out.println("I am studying");
Thread.sleep(1000);
}
@Override
public void work() {
System.out.println("I am a teacher~~~");
System.out.println("I am working");
Thread.sleep(1000);
}
}
- 测试(是不是感觉很方便呢_)
public static void main(String[] args) {
MyProxy myProxy=new MyProxy();
Human student=(Human)myProxy.bind(new Student());
student.eat();
student.study();
student.sleep();
student.work();
Human teacher=(Human)myProxy.bind(new Teacher());
teacher.work();
teacher.sleep();
teacher.study();
teacher.eat();
}
- 结果
I am eating
===============your sleep time is 201
I am studying
===============your sleep time is 1000
I am sleeping
===============your sleep time is 2001
I am working
===============your sleep time is 1000
I am a teacher~~~
I am working
===============your sleep time is 1002
I am a teacher~~~
I am sleeping
===============your sleep time is 2001
I am a teacher~~~
I am studying
===============your sleep time is 1000
I am a teacher~~~
I am eating
===============your sleep time is 201