代理模式:代理模式就是引入一个代理对象,通过代理对象实现对原对象的引用。代理模式是一种对象结构型。
public class Proxy implements Subject
{
private RealSubject realSubject = new RealSubject();
public void preRequest()
{…...}
public void request()
{
preRequest();
realSubject.request();
postRequest();
}
public void postRequest()
{……}
}
来自:《设计模式》一书归纳分类
下面介绍一下静态代理和动态代理
代理模式分为静态代理和动态代理 • 静态代理:静态代理就是编译阶段就生成代理类来完成对代理对象的一系列操作。 • 动态代理:动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。
静态代理:静态代理就是编译阶段就生成代理类来完成对代理对象的一系列操作。 主题接口:
public interface Subject {
abstract public void request();
}
目标对象:
public class RealSubject implements Subject {
public void request() {
System.out.println( " From real subject. " );
}
}
代理对象:
public class StaticProxySubject implements Subject {
private RealSubject realSubject; // 以真实角色作为代理角色的属性
public ProxySubject() { }
public void request() { // 该方法封装了真实对象的request方法
//懒加载,用的时候才加载
if ( realSubject == null ) {
realSubject = new RealSubject();
}
realSubject.request(); // 此处执行真实对象的request方法
}
}
编写客户端类:
public class Client{
StaticProxySubject sps = new StaticProxySubject();
sps.request();
}
动态代理:动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。 生成动态代理的方法有很多: JDK中自带动态代理,CGlib, javassist等。
Proxy类。该类即为动态代理类,该类最常用的方法为:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
。
newProxyInstance()方法用于根据传入的接口类型interfaces返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示被代理类实现的接口列表,第三个参数h表示所指派的调用处理程序类。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInvocationHandler implements InvocationHandler {
private Class<?> target;//委托类
public MyInvocationHandler(Class<?> target){
this.target=target;
}
//实际执行类bind
public Object bind(Class<?> target){
//利用JDK提供的Proxy实现动态代理
return Proxy.newProxyInstance(target.getClassLoader(),
new Class[]{target},this);
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
/**代理环绕**/
//执行实际的方法
Object invoke = method.invoke(target, args);
return invoke;
}
}
CGLIB动态代理实现相关类需要在项目中导入 cglib-nodep-2.1_3.jar ,主要涉及两个类:
MethodInterceptor接口。它是代理实例的调用处理程序实现的接口,该接口中定义了如下方法:public Object intercept(Object proxy, Method method, Object[] arg2, MethodProxy mp);
intercept()方法中第一个参数proxy表示代理类,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组,第四个参数mp用 来去调用被代理对象方法
package com.demo;
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 MyInterceptor implements MethodInterceptor{
private Object target; ;//代理的目标对象
public MyInterceptor(Object target) {
this.target = target;
}
//proxy 在其上调用方法的代理实例 method拦截的方法 args 拦截的参数
//invocation 用来去调用被代理对象方法
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy invocation) throws Throwable {
//1.记录日志 2.时间统计开始 3.安全检查
Object retVal = invocation.invoke(target, args);
//4.时间统计结束
return retVal;
}
//创建代理对象的方法
public Object proxy(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();//该类用于生成代理类
enhancer.setSuperclass(this.target.getClass());//设置父类
enhancer.setCallback(this);//设置回调用对象为本身
return enhancer.create();
}
}