像代理服务器一样,你想访问真实服务器不直接访问而是通过一个中转站,代理服务器访问;
调用真实对象的一个方法不直接调用,而是通过产生的一个代理对象调用。
人家是动态编程,需要在原来的方法的功能基础上再添加一些功能,而不用改变这个方法的签名,原来调用这个方法的类依然能正常工作。搜索
比如,现在要把一段文本发送给另一个人,普通方法是 void send(File a),现在我们弄出个特性,就像 Spring AOP 那样,在 send 之前给这个 a 压缩一下。原来的程序没有压缩功能,现在我们需要添加的话而不改变原来所有的代码的话就得用类似 AOP 这样的代码来处理。
代理分为两步:第一,先产生一个代理对象,并和真实的对象关联起来,产生代理关系;第二,实现代理对象的代理逻辑方法,这里一般都是由一个实现一个接口做的,JDK动态代理用java.lang.reflect.InvocationHandler这个接口;CGLIB用org.springframework.cglib.proxy.MethodInterceptor接口。
首先是JDK动态代理的代码:因为JDK动态代理必须借助一个接口才能实现产生代理对象:
定义一个接口
public interface Youplando {
public void dosomething(String string);
}
package 设计模式;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class Youwanttodo implements Youplando{
@Override
public void dosomething(String string) {
// TODO Auto-generated method stub
System.out.println("我想做"+string);
}
}
/**
* @author Administrator
* JDK代理分为两步:
* 1.代理对象和真实对象简历代理关系
* 2.实现代理对象的代理逻辑方法
*/
class JDKproxyExample implements InvocationHandler{
//真实对象
private Object target = null;
/**
* JDK代理第一步:~~~~~
* newProxyInstance的三个参数:第一个是target本身的类加载器;
* 第二个是代理对象下挂在哪些接口下
* 第三个是实现方法逻辑的代理类,这里就是JDKproxyExample这个当前类,必须实现InvocationHandler接口,重写invoke方法
* @param target 真实的对象
* @return 代理对象
*/
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance
(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
/**
* JDK代理第二步:~~~~~
* @param proxy 代理对象,
* @param method 调用的方法
* @param args[] 方法参数列表
* @return Object 代理结果
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//相当于反射调用了真实对象的方法
System.out.println("调用真实方法前哦");
Object object = method.invoke(target, args);
System.out.println("调用真实方法后哦");
return object;
}
}
public class JDKproxy {
public static void main(String[] args) {
//先实例化JDKproxyExample,用它来代理
JDKproxyExample jdk = new JDKproxyExample();
//真实对象
Youwanttodo realinstance = new Youwanttodo();
//产生代理对象proxy;
Youplando proxy = (Youplando) jdk.bind(realinstance);
//代理对象调用方法
proxy.dosomething("我我想做的");
}
}
CGLIB动态代理,不需要接口,但是是spring的代理包:
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
package Test;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
class Iwangtodo{
public void Iwangtodo(String string) {
System.out.println("i really wang to be"+string);
}
}
class CglibProxyExample implements MethodInterceptor{
/**
* 还是第一步!!!!!!!!!!
* 生成CGLIB代理对象
* @param cls 真实对象
* @return 代理对象
*/
public Object getProxy(Class cls) {
//CGLIB enhancer增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
enhancer.setCallback(this);
//返回代理对象
return enhancer.create();
}
/**
* 还是第二部!!!!!!!!!
* 生成CGLIB代理对象
* @param proxy 代理对象
* @param method 调用方法
* @param arg 方法参数
* @param methodproxy 方法代理
* @return 代理结果
*/
public Object intercept(Object proxy, Method method, Object[] arg,
MethodProxy methodproxy) throws Throwable {
// TODO Auto-generated method stub
System.out.println("调用真实方法前");
Object result = methodproxy.invokeSuper(proxy, arg);
System.out.println("调用真实方法后");
return result;
}
}
public class CGLIBproxy {
public static void main(String[] args) {
//代理实例
CglibProxyExample cglib = new CglibProxyExample();
//用代理实例产生一个代理对象
Iwangtodo iwangtodo = (Iwangtodo) cglib.getProxy(Iwangtodo.class);
//代理对象调用方法
iwangtodo.Iwangtodo("攻城狮!!");
}
}
拦截器代码:
package 设计模式;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*实现了拦截器接口*/
class InterceptorImp implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
// TODO Auto-generated method stub
System.out.println("反射前");
return false;
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
// TODO Auto-generated method stub
System.out.println("取代了被代理对象的方法");
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
// TODO Auto-generated method stub
System.out.println("反射后");
}
}
/*被调用方法的类,实现了接口*/
class Youwanttodo implements Youplando{
@Override
public void dosomething(String string) {
// TODO Auto-generated method stub
System.out.println("我想做"+string);
}
}
/*JDK动态代理中使用拦截器*/
public class InterceptorJdkProxy implements InvocationHandler {
private Object target;//真实对象
private String interceptorClass = null;//拦截器全限定名
//传入真实对象,和拦截器名字
public InterceptorJdkProxy(Object target,String interceptorClass) {
// TODO Auto-generated constructor stub
this.target = target;
this.interceptorClass = interceptorClass;
}
/*第一步,取得代理对象*/
public static Object bind(Object target,String interceptorClass) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), new InterceptorJdkProxy(target,interceptorClass));
}
/*第二步实现代理逻辑方法*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
if (interceptorClass==null) {
//如果没有拦截器,调用真实对象的方法了
return method.invoke(target, args);
}
//返回代理结果
Object result = null;
/*生成拦截器*/
Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
if (interceptor.before(proxy, target, method, args)) {
//before为true;反射方法
result = method.invoke(target, args);
}else {
//before为false
interceptor.around(proxy, args, method, args);
}
//后置方法
interceptor.after(proxy, target, method, args);
return result;
}
public static void main(String[] args) {
//代理对象
Youplando proxy = (Youplando) InterceptorJdkProxy.bind(new Youwanttodo(), "设计模式.InterceptorImp");
proxy.dosomething("a goodboy");
}
}