声明:文章内容根据大牛博客的内容,自己理解后,给自己做的学习笔记,文末会附上大牛博客地址链接。有需要沟通交流的可加我QQ群:425120333
代理分为静态代理和动态代理,静态代理比较好理解,关键是构建一个代理类,里面有个属性是目标对象(被代理的对象)。
代理类有着和目标对象一样的方法(可以是实现同一个接口来保证),然后根据需要对目标对象里的行为进行变动。
代码示例如下:
public class StaticProxy {
public static void main(String[] args) {
OriginClass origin = new OriginClass();
origin.print();
origin.print("test");
OriginClassProxy originProxy = new OriginClassProxy(origin);
originProxy.print();
originProxy.print("test");
}
}
/**
* @author caiqibin
* @introduce:目标对象类
*
*/
class OriginClass {
public void print() {
System.out.println("无参方法");
}
public void print(String arg) {
System.out.println("有参方法 :" + arg);
}
}
/**
* @author caiqibin
* @introduce:代理类
*
*/
class OriginClassProxy {
//通过持有目标对象来改变目标对象的行为
OriginClass originClass;
public OriginClassProxy(OriginClass originClass) {
this.originClass = originClass;
}
public void print() {
System.out.println("通过代理调用");
originClass.print();
}
public void print(String arg) {
System.out.println("不用原有的方法,而是调用代理方法:" + arg);
}
}
关于动态代理,并不是直接创建代理类,而是通过反射实现的,主要是为很多对象添加一样的额外行为时比较常用(像spring的AOP),
当然为单个对象通过动态代理创建额外的行为也是可行的。
动态代理的对象要求是接口或者是实现了接口的对象(不是绝对的,可以是普通对象,但需要和接口有同名方法,并且要在代理中自己通过反射调用)
public class DynamicProxy {
public static void main(String[] args) {
ZhangSan zhangSan = new ZhangSan();
Person zhangSanProxy = (Person) Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(), new Class[] { Person.class }, new ZhangSanProxy(zhangSan));
zhangSanProxy.print();
zhangSanProxy.print("111");
}
}
/**
* @author caiqibin
* @introduce:接口类
*
*/
interface Person {
void print();
void print(String arg);
}
/**
* @author caiqibin
* @introduce:具体实现类
*
*/
class ZhangSan implements Person {
@Override
public void print() {
System.out.println("i am zhang san");
}
@Override
public void print(String arg) {
System.out.println("i am zhang san ,say:" + arg);
}
}
class ZhangSanProxy implements InvocationHandler {
ZhangSan zhangSan;
public ZhangSanProxy(ZhangSan zhangSan) {
this.zhangSan = zhangSan;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过参数和方法名判断要调用的是那个方法
if (args != null && "print".equals(method.getName())) {
System.out.println("方法执行前,输出");
}
return method.invoke(zhangSan, args);
}
}
控制台输出:
i am zhang san
方法执行前,输出
i am zhang san ,say:111
从输出中可以看出只有有参方法,执行了代理中的输出,通过方法名和参数可以控制类中任意一个方法,去执行我们想要的操作。
这里的代理时针对ZhangSan这个具体实现类,不是针对Person接口的,如果是针对接口的,实现了该接口的所有类都会出现统一的拦截处理。
有兴趣的可以自己动手试试看看。关于动态代理的原理可参考下面的链接,
参考大牛博客链接:http://www.cnblogs.com/zuoxiaolong/p/pattern3.html