代理模式:
代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象和一个委托类的对象关联,代理类的对象本身并不是真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种:
静态代理:创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
动态代理:在程序运行时,运用反射机制动态创建而成。
公共接口:
package com.learns.proxy;
public interface Count {
// 查看帐号方法
public void queryCount();
// 修改帐号方法
public void updateCount();
}
接口实现类:
package com.learns.proxy;
public class CountImpl implements Count {
public void queryCount()
{
System.out.println("查看账户方法");
}
public void updateCount()
{
System.out.println("修改账户方法");
}
}
一、静态代理
package com.learns.proxy;
public class CountProxy implements Count {
private CountImpl countImpl;
public CountProxy(CountImpl countImpl)
{
this.countImpl = countImpl;
}
public void queryCount()
{
System.out.println("查询处理之前");
countImpl.queryCount();
System.out.println("查询处理之后");
}
public void updateCount()
{
System.out.println("修改处理之前");
countImpl.updateCount();
System.out.println("修改处理之后");
}
}
测试类:
package com.learns.proxy;
public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
二、JDK动态代理
JDK动态代理使用到一个Proxy类和一个InvocationHandler接口。Proxy仅支持interface代理(也就是代理类必须实现接口)
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
Proxy类:
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
package com.learns.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class CountProxyFactory implements InvocationHandler {
private Object target;
public Object bind(Object target)
{
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
{
boolean objFlag = method.getDeclaringClass().getName().equals("java.lang.Object");
Object result = null;
if(!objFlag)
{
System.out.println("代理before");
}
result = method.invoke(this.target, args);
if(!objFlag)
{
System.out.println("代理after");
}
return result;
}
}
测试类:
package com.learns.proxy.jdk;
import com.learns.proxy.Count;
import com.learns.proxy.CountImpl;
public class CountProxyTest {
public static void main(String[] args)
{
// 下面使用JDK的代理类,一个代理可以代理很多接口
Count count = (Count)new CountProxyFactory().bind(new CountImpl());
System.out.println(count);
count.queryCount();
}
}
三、CGLIB动态代理
针对JDK仅支持实现接口的委托类进行代理的缺陷,CGLIB解决了这个问题。 使其委托类也可是非接口实现类。
CGLIB内部使用到ASM,所以需要引入asm-3.3.jar、cglib-2.2.2.jar
注意:cglib版本为3.0或3.1,asm版本为3.1时。版本冲突,报错java.lang.IncompatibleClassChangeError: class net.sf.cglib.core.DebuggingClassWriter has interface org.objectweb.asm.ClassVisitor as super class。使用cglib2.2可解决此问题,该版本中的DebuggingClassWriter的父类为ClassWriter
非接口实现类:
package com.learns.proxy.cglib;
public class Person {
public void show()
{
System.out.println("showing");
}
}
代理类:
package com.learns.proxy.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CountCglibProxyFactory implements MethodInterceptor {
private Object target;
public Object getInstance(Object target)
{
this.target = target;
return Enhancer.create(this.target.getClass(), this);
}
public Object intercept(Object obj,Method method,Object[] args,MethodProxy methodProxy) throws Throwable
{
boolean objFlag = method.getDeclaringClass().getName().equals("java.lang.Object");
if(!objFlag)
{
System.out.println("before");
}
Object result = null;
result = methodProxy.invokeSuper(obj, args);
if(!objFlag)
{
System.out.println("after");
}
return result;
}
}
测试类:
package com.learns.proxy.cglib;
import com.learns.proxy.Count;
import com.learns.proxy.CountImpl;
public class CountCglibProxyTest {
public static void main(String[] args) {
Count count = (Count)new CountCglibProxyFactory().getInstance(new CountImpl());
count.updateCount();
Person person = (Person)new CountCglibProxyFactory().getInstance(new Person());
System.out.println(person);
person.show();
}
}
参考文章:
http://blog.csdn.net/yuanlaishinizhu/article/details/12998847