一)、创建动态代理的步骤
1、主题接口
2、代理类
3、真实类
4、使用类
1)主体接口中定义了代理类和真实类的的公共接口方法,代理类和真实类分别实现主体接口,真实类实现了接口方法的具体逻辑,代理类也实现了同样的接口方法,在方法中调用真实类的逻辑,相当于拿到了被代理人的授权,执行被代理人拥有的功能。
2)在实用类中,利用java的多态特性,使用公共接口,接收代理类,接收代理类对象,使用代理类调用公共方法,实现真实类的具体逻辑。
二)、使用jdk实现动态代理
一、为什么要使用动态代理?
1)、原有的静态代理一个接口对应一个代理类,当真实主题很多时,要写多个代理类
2)、当接口有变动时,真实类和代理类都要变动。使用了动态代理,代理类是动态的生成的,代理类动态的实现公共接口的方法
二、步骤
1、主题接口
2、真实类
3、InvocationHanlder接口的实现类
Proxy.newInstance(ClassLoader loader,class<?>[] inteface,InvocationHander hanlder) //创建一个代理实例 invoke(Object proxy,Method method,args)//代理类的实现逻辑
4、使用类
主题接口:
/** * 数据库查询的公共接口 */ public interface DBQueryInterface { public String request(); }
真实类:
public class DBQuery implements DBQueryInterface{ /** * 模拟重量级对象,对象初始化时需要进行数据库连接 */ DBQuery(){ try { Thread.sleep(10000); } catch (InterruptedException e) { e.printstacktrace(); } } /** * 数据库查询的具体逻辑实现 * @return */ @Override public String request() { return "我正在执行数据库查询操作"; } }
动态代理类:
public class DBQueryJdkProxy implements InvocationHandler { DBQuery dbQuery = null; /** * 获取代理对象 */ public Object bind(){ return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{DBQueryInterface.class},new DBQueryJdkProxy()); } /** * invoke方法是代理逻辑的具体实现 */ @Override public Object invoke(Object proxy,Object[] args) throws Throwable { if(dbQuery == null){ //延迟加载,当使用到时才创建重量级对象 dbQuery = new DBQuery(); } return dbQuery.request(); } }
使用类:
public class Client { public static void main(String[] args) { //初始化时先加载代理对象 DBQueryInterface JdkProxy= (DBQueryInterface) new DBQueryJdkProxy().bind(); //使用时才创建真实的对象 String result = JdkProxy.request(); System.out.println(result); } }
结果:
我正在执行数据库查询操作
改进: 使用动态代理实现延迟加载同时增强原有类的功能
主题接口:
/** * 数据库查询的公共接口 */ public interface DBQueryInterface { public String request(); }
真实类:
public class DBQuery implements DBQueryInterface{ /** * 模拟重量级对象,对象初始化时需要进行数据库连接 */ DBQuery(){ try { Thread.sleep(10000); } catch (InterruptedException e) { e.printstacktrace(); } } /** * 数据库查询的具体逻辑实现 * @return */ @Override public String request() { return "我正在执行数据库查询操作"; } }
动态代理类:
/** * 使用动态代理创建数据库查询的代理对象 * 1、实现InvocationHandler接口 * 2、调用Proxy.newInstance()动态的创建代理对象 */ public class DBQueryJdkProxy implements InvocationHandler { Object target; /** * 获取代理对象 */ public Object bind(Object target){//target是真实类对象,给给定的真实类对象创建一个代理,由代理去完成真实类的工作 this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } /** * 增强原有类的功能 */ @Override public Object invoke(Object proxy,Object[] args) throws Throwable { System.out.println("事物开始"); System.out.println(method.invoke(target,args)); System.out.println("事物结束"); return null; } }
使用类:
public class Client { public static void main(String[] args) { //加载数据库查询代理工厂 DBQueryJdkProxy dbQueryJdkProxy = new DBQueryJdkProxy(); //给指定的对象创建代理工厂 DBQueryInterface proxy = (DBQueryInterface) dbQueryJdkProxy.bind(new DBQuery()); proxy.request(); } }