代理模式是Java常见的设计模式,代理类和为拖类功能相同,代理类负责增强功能,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 就像Spring Aop的实现,再特定方法执行前或后执行特定的拦截器,使用的就是动态代理。 代理分为两种: 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。 动态代理:程序运行过程中,由反射机制动态创建而成。
下面分别讨论静态代理、jdk动态代理和cglib动态代理,Book.java和BookImpl.java为三种代理方法的公共类,直接上代码: 1、Book.java package com.proxy; public interface Book { //定义图书添加接口 public void addBook(); } 2.BookImpl.java package com.proxy; //委托类,包括业务逻辑 public class BookImpl implements Book{ @Override public void addBook() { System.out.println("添加图书"); } } 静态代理类: //这是一个代理类,增强BookImpl功能 public class BookProxy implements Book{
private BookImpl bookImpl;
public BookProxy(BookImpl bookImpl) {
this.bookImpl = bookImpl;
}
@Override
public void addBook() {
System.out.println("代理前");
bookImpl.addBook();
System.out.println("代理后");
}
} Test.java public class Test { public static void main(String[] args) { BookProxy proxy = new BookProxy(new BookImpl()); proxy.addBook(); }
} 输出结果为: 代理前 添加图书 代理后 观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。 Jdk动态代理设计到一个接口和一个类: InvocationHandler接口: public interface InvocationHandler { public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; } Proxy类: Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力 jdk动态代理示例:
public class BookProxy implements InvocationHandler{
private Object target;
/** * 绑定委托对象并返回一个代理类 */
public Object bind(Object target){ this.target = target; //取得代理对象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("代理前");
result = method.invoke(target, args);
System.out.println("代理后");
return result;
}
Test.java public class TestProxy {
public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
} } 输出结果为: 代理前 添加图书 代理后 但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。 Cglib动态代理 public class BookProxy implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*/
public Object getInstance(Object target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("代理前");
arg3.invokeSuper(arg0, arg2);
System.out.println("代理后");
return null;
}
} Test.java public class Test {
public static void main(String[] args) {
BookProxy cglib = new BookProxy();
BookImpl bookCglib = (BookImpl) cglib.getInstance(new BookImpl());
bookCglib.addBook();
}
} 输出结果为: 代理前 添加图书 代理后