代理模式
包括
静态代理:是在java文件编译前,手动写好代理类并绑定了代理关系, 所以只能代理绑定的类或接口。
动态代理:是通过反射原理,在程序运行的时候动态的生成的代理对象,所以可以代理任意的类或对象。
代理模式作用 为目标对象提供一个代理对象,并由代理对象控制对目标对象的调用 类似于中介
静态代理:是在java文件编译前,手动写好代理类并绑定了代理关系, 所以只能代理绑定的类或接口。
有接口/功能 (声明业务方法)
被代理类(用户) implement 实现 这个接口/功能 重写方法 (具体自己业务方法)
代理类 也要implement 实现 这个功能/接口
构造注入这个接口/功能(目标对象)
重写方法中
调用目标对象的业务方法 并附加其他方法(做其他事情)
例1

public interface Buyer { /** * 查看房屋 * @return 反馈 */ public String havealook(); }

public class RealBuyer implements Buyer { @Override public String havealook() { System.out.println("*****实地查看一下"); return "*****一些意见"; } }

public class IntermediaryImpl implements Buyer { /** * 被代理的目标对象 */ private Buyer target; public IntermediaryImpl(Buyer target) { this.target = target; } /** * 对目标对象业务进行代理 */ @Override public String havealook() { before(); String feedback = target.havealook(); // 执行目标对象的实际业务 after(); return "看房记录:买家反馈“" + feedback + "”"; } public void before() { System.out.println("前期准备。"); System.out.println("查找房源。"); System.out.println("和卖家沟通时间。"); } public void after() { System.out.println("后期跟踪"); System.out.println("和买家沟通意见。"); } }
public class BuyerTest { public static void main(String[] args) throws Exception { RealBuyer user=new RealBuyer();//创建真是用户 Buyer buyer = new IntermediaryImpl(user);//创建代理对象[中介],将被代理者交给中介 管理 String result = buyer.havealook(); System.out.println(result); } }
时序图如下
例2

public class Movie { public static String payTicket(int vip,String ticketName){ try { if (vip==0) { Thread.sleep(5000); }else if (vip==1) { Thread.sleep(4000); }else if (vip==2) { Thread.sleep(2000); }else if (vip==3) { } } catch (Exception e) { // TODO: handle exception } return ticketName+" 购买成功!"; } }

public interface User { /** * 购买电影票 * @return */ public String buyTicket(); }

public class RealUser implements User{ public String buyTicket() { System.out.println("排队中...."); return "电影票: 火影忍者"; } /** * 0级 VIP * @return */ public int getVIP() { return 0; } }

public class YellowCattle implements User { private User user; public YellowCattle(User user) { this.user = user; } @Override public String buyTicket() { //增加额外功能 //管理被代理者: 辅助他完成功能 String ticketInfo=user.buyTicket(); Movie obj=new Movie(); String rs=obj.payTicket(getVIP(), ticketInfo); return rs; } /** * 3级 VIP * @return */ public int getVIP() { return 3; } }
public class TicketTest { public static void main(String[] args) { //创建真实用户 User user=new RealUser(); //创建代理对象 YellowCattle obj=new YellowCattle(user);//将被代理者 交给 代理对象管理 String str=obj.buyTicket(); System.out.println("<===找黄牛买票===>"+str); /** * 不希望用户接触 或 用户不善长的功能 --->交给代理对象完成. */ RealUser realUser=new RealUser(); String result2= Movie.payTicket(realUser.getVIP(), realUser.buyTicket()); System.out.println("<****自己买票****>" +result2); } }
时序图如下
没有接口/功能(作为功能类的方法存在)
功能类 必须满足一定条件 (特殊属性) 要完成的方法
被代理类(用户) 要完成的方法 (一般属性)
代理类extends 继承被代理对象 代理类有(特殊属性)
重写方法中
通过功能类 调用 代理类特殊属性 被代理对象要完成的方法

public class Movie { public static String payTicket(int vip,String ticketName){ try { if (vip==0) { Thread.sleep(5000); }else if (vip==1) { Thread.sleep(4000); }else if (vip==2) { Thread.sleep(2000); }else if (vip==3) { } } catch (Exception e) { // TODO: handle exception } return ticketName+" 购买成功!"; } }

public class RealUser { public String buyTicket() { System.out.println("排队中...."); return "电影票: 火影忍者"; } /** * 0级 VIP * @return */ public int getVIP() { return 0; } }

public class YellowCattle extends RealUser { @Override public String buyTicket() { //增加额外功能 //管理被代理者: 辅助他完成功能 String ticketInfo=super.buyTicket(); Movie obj=new Movie(); String rs=obj.payTicket(getVIP(), ticketInfo); return rs; } /** * 3级 VIP * @return */ public int getVIP() { return 3; } }
public class TicketTest { public static void main(String[] args) { //创建代理对象 YellowCattle obj=new YellowCattle();//将被代理者 交给 代理对象管理 String str=obj.buyTicket(); System.out.println(str); } }
时序图如下
动态代理:是通过反射原理,在程序运行的时候动态的生成的代理对象,所以可以代理任意的类或对象。
JDK动态代理 InvocationHander接口 处理器
有接口/功能 (声明业务方法) (特殊属性)
被代理类(用户) implement 实现 这个接口/功能 重写方法 (具体自己业务方法) (一般属性)
代理类 implement 实现 InvocationHander接口 (特殊属性)
构造注入Object对象(目标对象)
重写方法invoke()中
通过反射调用目标对象的业务方法 得到方法参数
功能类调用 代理类 (特殊属性) 目标对象的返回值(恰好是功能类的参数)

public class Movie { /** * 万达售票: 根据VIP级别排队购买电影票 * @param vip * @param ticketName * @return */ public static String payTicket(int vip,String ticketName){ try { if (vip==0) { Thread.sleep(5000); }else if (vip==1) { Thread.sleep(4000); }else if (vip==2) { Thread.sleep(2000); }else if (vip==3) { } } catch (Exception e) { // TODO: handle exception } return ticketName+" 购买成功!"; } }

public interface User { /** * 购买电影票 * @return */ public String buyTicket(); }

public class RealUser implements User{ public String buyTicket() { System.out.println("排队中...."); return "电影票: 火影忍者"; } /** * 0级 VIP * @return */ public int getVIP() { return 0; } }

public class IntermediaryInvocationHandler implements InvocationHandler { /** * 被代理的目标对象 */ private Object target; public void setTarget(Object target) { this.target = target; } /** * 为被代理的接口方法定义的代理业务规则 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Method对象.invoke(对象实例,参数): 反射方式,执行被代理对象的指定方法 String ticketName = (String) method.invoke(target, args); String result= Movie.payTicket(getVIP(), ticketName); return result; } /** * 10级 VIP * @return */ public int getVIP() { return 10; } }
public class TicketTest { public static void main(String[] args) throws Exception { //创建真实对象 Object target=new RealUser(); //创建 处理程序 IntermediaryInvocationHandler handler = new IntermediaryInvocationHandler(); //设置 处理程序操作的真实对象 handler.setTarget(target); //获得代理对象: 根据指出的接口和真实类,以实现接口的方式为真实类创建代理对象. User user =(User) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); //当使用代理对象访问方法时,会将方法调用指派给"处理程序[Handler]". 处理程序会执行invoke() String result = user.buyTicket(); System.out.println(result); } }
时序图如下
CGLIB动态代理 MethodInterceptor接口 拦截器
没有接口/功能(被代理类 自己的业务方法)
代理工厂类
实例化业务规则类
ctreate()方法中
实例化Enhancer 回调业务规则对象 方法
将目标对象作为父类反射动态创建目标对象的子类
定义业务规则类 implement 实现 MethodInterceptor接口
重写intercept()方法中
增加一些事情 并调用代理类的父类的方法
新建lib文件夹 导入jar包 cglib-nodep-3.3.0.jar log4j-1.2.17.jar
新建resources文件夹

# rootLogger是所有日志的根日志,修改该日志属性将对所有日志起作用 # 下面的属性配置中,所有日志的输出级别是debug,输出源是con log4j.rootLogger=debug,con # 定义输出源的输出位置是控制台 log4j.appender.con=org.apache.log4j.ConsoleAppender # 定义输出日志的布局采用的类 log4j.appender.con.layout=org.apache.log4j.PatternLayout # 定义日志输出时间格式 log4j.appender.con.layout.ConversionPattern=%d{MM-dd HH:mm:ss}[%p]%c - %m%n
public class RealBuyer { private Logger logger = Logger.getLogger(RealBuyer.class); public String havealook() { logger.debug("---->>>>>>>实地查看一下"); return "---->>>>>>>一些意见"; } }
public class IntermediaryMethodInterceptor implements MethodInterceptor { private Logger logger = Logger.getLogger(IntermediaryMethodInterceptor.class); /** * 为被代理的方法定义的代理业务规则 */ @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { before(); Object feedback = methodProxy.invokeSuper(proxy, args); // 调用父类原始的方法 after(); return "看房记录:买家反馈“" + feedback + "”"; } public void before() { logger.debug("前期准备。"); logger.debug("查找房源。"); logger.debug("和卖家沟通时间。"); } public void after() { logger.debug("后期跟踪"); logger.debug("和买家沟通意见。"); } }
public class IntermediaryCglibProxyFactory { //MethodInterceptor接口 实现类 private static IntermediaryMethodInterceptor callback = new IntermediaryMethodInterceptor(); /** * 工厂方法 * @param target 需要被代理的类型,即代理类需要继承的父类型 * @return 代理类的实例 */ public static <T> T create(Class<T> target) { //增强器 //Enhancer负责动态生成代理 = 目标对象的子类 Enhancer enhancer = new Enhancer(); enhancer.setCallback(callback); // 为重写的方法指定回调的MethodInterceptor enhancer.setSuperclass(target); // 指定要继承的父类型,即需要被代理的类型 return (T) enhancer.create(); // 动态生成子类,创建子类实例并返回 } }
public class BuyerTest { private Logger logger = Logger.getLogger(BuyerTest.class); @Test public void havealookCglibProxy() throws Exception { RealBuyer buyer = IntermediaryCglibProxyFactory.create(RealBuyer.class); String result = buyer.havealook(); logger.debug(result); } }
时序图如下