代理模式
1.定义
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
2.类图
Uml图:
简单结构示意图:
3. 静态代理
以雇员通过中介找工作为例
抽象接口
Employer.java
package proxy; public interface Employer { void offerJob(); }
公司,提供真实工作
Company.java
中介,代理找工作package proxy; public class Company implements Employer { @Override public void offerJob() { System.out.println("got a nice job!"); } }
JobAgency.java
雇员,通过中介找工作package proxy; public class JobAgency implements Employer { private Company company = new Company(); @Override public void offerJob() { System.out.println("pay agent fee!"); company.offerJob(); } }
Employee.java
package proxy; public class Employee { public static void main(String[] args) throws Throwable { Employer employer = new JobAgency(); employer.offerJob(); } }
4.通过JDK动态代理
继承InvocationHandler生成代理handler,handler可以多个类共用
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class JobAgencyHandler implements InvocationHandler { // 要代理的原始对象 private Object objj; public JobAgencyHandler(Object obj) { super(); this.objj = obj; } @Override public Object invoke(Object obj, Method method, Object[] args) throws Throwable { //入参obj为代理类对象,method为业务类的方法对象,args为入参,这里执行完 //代理逻辑要调用业务逻辑的时候,obj不会用到,obj的作用待探索 System.out.println(obj.getClass().getName()); System.out.println(method.getName()); System.out.println("pay agent fee!"); Object result = null; //调用之前 doProcess // 调用原始对象的方法 //主要这里调用的对象是构造函数传入的业务类对象objj,而不是方法入参obj result = method.invoke(objj, args); // 调用之后 doProcess return result; } }
雇员(Employee)在使用动态代理找工作
package proxy; import java.lang.reflect.Proxy; public class Employee { public static void main(String[] args) throws Throwable { try { // 静态代理 Employer employer = new JobAgency(); employer.offerJob(); // 动态代理 //获得要被代理的对象 Employer com = new Company(); //新建代理handler,将业务对象传入 JobAgencyHandler handler = new JobAgencyHandler(com); //生成代理类,主要引用和强转型必须使用接口(Employer) Employer proxy = (Employer) Proxy.newProxyInstance(com.getClass() .getClassLoader(), com.getClass().getInterfaces(), handler); //调用业务方法 proxy.offerJob(); } catch (Exception e) { e.printStackTrace(); } } }
5.通过CGLIB动态代理
原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
jobAgencyCglib.java
package proxy; 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 jobAgencyCglib implements MethodInterceptor { private Object target; /** * 创建代理对象 * * @param target * @return */ 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(arg0.getClass().getName()); System.out.println(arg1.getName()); System.out.println("pay agent fee!"); arg3.invokeSuper(arg0, arg2); return null; } }
employee.java
package proxy; import java.lang.reflect.Proxy; public class Employee { public static void main(String[] args) throws Throwable { //CGLIB //获得要被代理的对象 Employer comc = new Company(); jobAgencyCglib cglib = new jobAgencyCglib(); Company proxyc = (Company)cglib.getInstance(comc); proxyc.offerJob(); } }