静态代理
某个对象提供一个代理,代理角色固定,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
举例子:小明现在想去追小红,但是他害羞不敢直接追,通过小代去追小红。这个时候,小明就是被代理类,小代就是代理类,因为小明要让小代去送公仔、送花、送巧克力,这些行为,小代肯定也是要有的,所以小明和小代是集成同一个接口。
最求者和代理者的公共行为:
/**
* 最求者要执行的方法
* 代理类和被代理类都要集成同一个接口,这样被代理类执行方法的时候,代理类执行同样的方法,对被代理类要执行的方法前后进行加强。
*/
public interface GiveGirl {
void giveDolls(); // 送公仔
void giveFlowers(); // 送花
void givechocolate(); // 送巧可力
}
被追求的人,也就是小红
public class SchoolGril {
private String name;
public SchoolGril(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
追求的人,也就是小明,也就是实现了具体的行为。
/**
* 追求者,也就是被代理类,通过被人去追求女朋友
*/
public class Pursuit implements GiveGirl {
SchoolGril schoolGril;
public Pursuit(SchoolGril schoolGril) {
this.schoolGril = schoolGril;
}
@Override
public void giveDolls() {
System.out.println(schoolGril.getName() + "," + "送你洋娃娃" );
}
@Override
public void giveFlowers() {
System.out.println(schoolGril.getName() + "," + "送你鲜花" );
}
@Override
public void givechocolate() {
System.out.println(schoolGril.getName() + "," + "送你巧克力" );
}
}
静态代理类,也就是小代,也实现了行为接口,毕竟你是代理人,不能完全执行被代理人小明的工作怎么行呢。
public class StaticProxy implements GiveGirl {
//代理的对象,说明是代理,那肯定要有被代理人了
Pursuit pursuit;
//传入代理需要追求者
public StaticProxy(SchoolGril schoolGril) {
pursuit = new Pursuit(schoolGril);
}
@Override
public void giveDolls() {
//被代理对象执行前做处理的地方
pursuit.giveDolls();
//被代理对象执行后做处理的地方
}
@Override
public void giveFlowers() {
//被代理对象执行前做处理的地方
pursuit.giveFlowers();
//被代理对象执行后做处理的地方
}
@Override
public void givechocolate() {
//被代理对象执行前做处理的地方
pursuit.givechocolate();
//被代理对象执行后做处理的地方
}
}
测试类
public class TestStaticProxy {
public static void main(String[] args) {
SchoolGril schoolGril = new SchoolGril("lisa");
StaticProxy staticProxy = new StaticProxy(schoolGril);
//代理执行的方法,将被代理对象隐藏起来
staticProxy.giveDolls();
staticProxy.giveFlowers();
staticProxy.givechocolate();
}
}
动态代理
相比于静态代理,动态代理在创建代理对象上更加的灵活,动态代理类的字节码在程序运行时,由Java反射机制动态产生。它会根据需要,通过反射机制在程序运行期,动态的为目标对象创建代理对象,无需程序员手动编写它的源代码。动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为反射机制可以生成任意类型的动态代理类。代理的行为可以代理多个方法,即满足生产需要的同时又达到代码通用的目的。
动态代理的两种实现方式:
-
JDK 动态代理
-
CGLIB动态代理
代理类也就是小代,需要实现InvocationHandler接口
/**
* 代理类
*/
public class DynamicProxy implements InvocationHandler {
// 目标对象的类型不固定,创建时动态生成
private Object target;
public DynamicProxy(Object target) {
this.target = target;
}
/**
* 1、调用目标对象的方法(返回Object)
* 2、增强目标对象的行为
* @param proxy 调用该方法的代理实例
* @param method 目标对象的方法
* @param args 目标对象的方法形参
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 增强行为
System.out.println("==============方法前执行");
// 调用目标对象的方法(返回Object)
Object result = method.invoke(target,args);
// 增强行为
System.out.println("方法后执行==============");
return null;
}
/**
* 得到代理对象
* public static Object newProxyInstance(ClassLoader loader,
* Class<?>[] interfaces,
* InvocationHandler h)
* loader:类加载器
* interfaces:接口数组
* h:InvocationHandler接口 (传入InvocationHandler接口的实现类)
*
*
* @return
*/
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
}
Proxy.newProxyInstance()是创建代理对象的方法。
测试类
public class TestDynamicProxy {
public static void main(String[] args) {
SchoolGril schoolGril = new SchoolGril("Mary");
Pursuit pursuit = new Pursuit(schoolGril);
//传入要代理的对象,小明
DynamicProxy dynamicProxy = new DynamicProxy(pursuit);
//获取代理的对象,小代
GiveGirl proxy = (GiveGirl) dynamicProxy.getProxy();
proxy.giveDolls();
}
}