什么是代理
这里的代理可以联系生活中的代理,就是代表某些人或事物做一些事情,举几个例子:1.中介就是一个典型的代理,你把房子挂到中介,中介就会帮你把房子的标价报给想买房的人;2.你打官司的时候,花钱请了律师,律师就会帮你打官司,替你说话..等等现实中有很多代理的例子。
为什么使用代理
还是引用上面的例子,你之所以把房子挂到中介,是因为你很忙,没时间处理,而且中介可以联系更多的买家;请律师,是因为律师懂得更多的法律知识,相当于对你进行了武装。
软件应用中的代理
经过上面对现实生活中代理的简单介绍,下面说一下我们编写软件应用中代理模式的使用。
在软件应用中,代理模式的使用有三种情况:静态代理,JDK动态代理),cglib动态代理;下面进行分别的介绍。
- 静态代理
静态代理是指被代理类和代理类都实现同一个接口,对于被代理类的方法访问需要通过代理类调用- 静态代理的缺点:
1、代理的职能单一,在代码中需要写多个代理来完成不同的功能
2、在编译器已经确定对被代理类的方法的调用,不适合做更多的扩展
示例代码:
首先是公用接口
/**
* Created by bitsino-001 on 2019/5/17.
* 通过房子中介演示静态代理
* 这是个买房者和中介的公用接口
*/
public interface SellHouse {
void price_house();
}
被代理类实现公用接口,这里就是卖房子的人
/**
* Created by bitsino-001 on 2019/5/17.
* 实际卖方的人(被代理类)
*/
public class Seller implements SellHouse {
@Override
public void price_house() {
System.out.println("我是房主,万科洋房,110平,售价150万!");
}
}
接下来是代理类也实现公用接口,这里就是房屋中介
/**
* Created by bitsino-001 on 2019/5/17.
* 中介代理类
*/
public class Zhongjie implements SellHouse {
//
Seller seller = new Seller();
@Override
public void price_house() {
System.out.println("我是房屋中介,房主急售!");
seller.price_house();
}
}
下面是测试代码
/**
* Created by bitsino-001 on 2019/5/17.
*/
public class TestProxy {
public static void main(String[] args) {
SellHouse sellHouse = new Zhongjie();
sellHouse.price_house();
}
}
输出结果:通过代理类调用了被代理类的方法,同时,也可以看做代理类对被代理类做了宣传,也可以叫做增强,这个概念在后面的学习中会看到,如果学习了spring ,对AOP有了解那么这个概念应该熟悉。
- JDK动态代理
JDK动态代理和静态代理类似,需要实现公共的接口,但是弥补了上面说的静态代理的缺点。动态代理是在运行时动态的为被代理类创建代理对象,公用接口中的方法都被转移到调用处理器一个集中的方法中执行,可以更加灵活的处理多个方法的调用执行。
示例代码:
package dynamic_proxy;
/**
* Created by bitsino-001 on 2019/5/17.
* 一个普通的用户,需要请律师代理他打官司
*/
public class User implements DaGuanSi {
@Override
public void juzheng() {
System.out.println("用户请律师帮忙举证");
}
@Override
public void susong() {
System.out.println("用户请律师帮忙诉讼");
}
}
package dynamic_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by bitsino-001 on 2019/5/17.
* 演示如何实现动态代理
*
*/
public class TestDynamicProxy {
public static void main(String[] args) {
//获得代理类,需要用到JDK中的 Proxy.newProxyInstance()方法
// 在Proxy.newProxyInstance()中需要传入三个参数
/* public static Object newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
* 第一个是被代理类的类加载器,第二个是被代理类实现的接口,第三个参数是用来动态调用方法的接口
* 想必介绍到这里,熟悉java反射的朋友应该想到了,动态代理是通过反射来实现的运行时方法调用
* */
User user = new User();
//获得代理对象
DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
@Override
//当通过代理对象调用xxx方法时就会调用下面的方法执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("各位好,我是代理律师");
Object invoke = method.invoke(user,args);//这里就是通过反射执行代理类的方法,也就是间接的调用被代理类的方法
System.out.println("本代理律师发言完毕");
return invoke;
}
});
proxy.juzheng();
proxy.susong();
}
}
为了演示动态代理的优势,我们再通过动态代理来为上面的卖房子的例子做一下实现,这次我们只需要将动态代理中的代理对象声名为Seller(卖房者),接口改成卖房子的公共接口,就会动态的生成代理对象,当调用代理对象的方法时,也会调用被代理对象的方法。
package dynamic_proxy;
import static_proxy.SellHouse;
import static_proxy.Seller;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by bitsino-001 on 2019/5/17.
* 演示如何实现动态代理
*
*/
public class TestDynamicProxy {
public static void main(String[] args) {
//获得代理类,需要用到JDK中的 Proxy.newProxyInstance()方法
// 在Proxy.newProxyInstance()中需要传入三个参数
/* public static Object newProxyInstance(ClassLoader loader,Class>[] interfaces,InvocationHandler h)
* 第一个是被代理类的类加载器,第二个是被代理类实现的接口,第三个参数是用来动态调用方法的接口
* 想必介绍到这里,熟悉java反射的朋友应该想到了,动态代理是通过反射来实现的运行时方法调用
* */
/* User user = new User();
//获得代理对象
DaGuanSi proxy = (DaGuanSi) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
@Override
//当通过代理对象调用xxx方法时就会调用下面的方法执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("各位好,我是代理律师");
Object invoke = method.invoke(user,args);//这里就是通过反射执行代理类的方法,也就是间接的调用被代理类的方法
System.out.println("本代理律师发言完毕");
return invoke;
}
});
proxy.juzheng();
proxy.susong();*/
Seller seller = new Seller();
//获得代理对象
SellHouse proxy = (SellHouse) Proxy.newProxyInstance(seller.getClass().getClassLoader(), seller.getClass().getInterfaces(), new InvocationHandler() {
@Override
//当通过代理对象调用xxx方法时就会调用下面的方法执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("各位好,我是代理律师");
Object invoke = method.invoke(seller,args);//这里就是通过反射执行代理类的方法,也就是间接的调用被代理类的方法
System.out.println("本代理律师发言完毕");
return invoke;
}
});
proxy.price_house();
}
}