在看Spring视频教程的时候看到有关动态代理的,之前没了解过,通过查API文档和网上一些别人写的东西好好了解了一下,才有了这篇文章
文章参考:http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/
动态代理可以为其他对象提供一种代理以控制对这个对象的访问,相当于在客户端和目标对象之间建立一座桥梁,这样客户端就可以通过这座桥梁(代理对象)来访问被代理类的方法,Java中动态代理主要用到 InvocationHandler接口和 Proxy类,InvocationHandler接口只有一个invoke()方法,我们编写的代理类都要实现这个接口,而Proxy类主要有四个静态方法,其详细情况可以查看API文档或源码,下面用具体代码实现我们的动态代理:
1、先创建一个接口:
public interface MethodDAO {
public void method1();
public void method2();
}
2、实现接口,重写方法:
public class MethodDAOImpl implements MethodDAO {
@Override
public void method1() {
System.out.println("方法1");
}
@Override
public void method2() {
System.out.println("方法2");
}
}
3、编写我们自己的代理类:
public class MethodDAOImplProxy implements InvocationHandler {
private MethodDAO methodDAO = new MethodDAOImpl();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("可在此处加入调用前要执行的逻辑···");
//调用我们写的方法
Object object = method.invoke(methodDAO, args);
System.out.println("可在此处加入调用后要执行的逻辑···");
return object;
}
}
4、客户端,测试代理:
public class TestMethodDAOImplProxy {
public static void main(String[] args) {
InvocationHandler handler = new MethodDAOImplProxy();
//返回代理类实例,这样就可以通过代理类的对象调用MethodDAO中的方法
MethodDAO methodDAO = (MethodDAO) Proxy.newProxyInstance(MethodDAO.class.getClassLoader(),
new Class[]{MethodDAO.class}, handler);
methodDAO.method1();
methodDAO.method2();
}
// 这里将newProxyInstance() 的源码贴出来,方便理解,想更详细的了解其运行过程是怎样代理的,还是在Debug下调试运行,
// 我也是调试很多次才弄懂的,其中用到很多反射的东西
// public static Object newProxyInstance(ClassLoader loader,
// Class<?>[] interfaces,InvocationHandler h)
// throws IllegalArgumentException {
// if (h == null) {
// throw new NullPointerException();
// }
// 获得与制定类装载器和一组接口相关的代理类类型对象
// Class cl = getProxyClass(loader, interfaces);
// 通过反射获取构造函数对象并生成代理类实例
// try {
// Constructor cons = cl.getConstructor(constructorParams);
// return (Object) cons.newInstance(new Object[] { h });
// } catch (NoSuchMethodException e) {
// throw new InternalError(e.toString());
// } catch (IllegalAccessException e) {
// throw new InternalError(e.toString());
// } catch (InstantiationException e) {
// throw new InternalError(e.toString());
// } catch (InvocationTargetException e) {
// throw new InternalError(e.toString());
// }
// }
}
运行结果:
可在此处加入调用前要执行的逻辑···
方法1
可在此处加入调用后要执行的逻辑···
可在此处加入调用前要执行的逻辑···
方法2
可在此处加入调用后要执行的逻辑···
使用动态代理的好处是显而易见的,比如我们想在调用method1()之前或者之后加一些判断或者逻辑方法,这时我们只要修改代理类的代码,而不用修改客户端的代码