代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
Java的三种代理模式:静态代理,JDK动态代理,CGLIB动态代理
接口IUserDao,接口实现类UserDao。
public interface IUserDao {
public void save();
}
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("数据保存操作");
}
}
1.静态代理
静态代理在使用时,需要定义接口或者父类,目标对象与代理对象一起实现相同的接口或者是继承相同的父类。
缺点:
因为代理对象与目标对象需要实现相同的接口,使得每个目标对象,都有一个代理类,从而产生非常多的代理类。
public class UserDaoProxy implements IUserDao {
//接收保存目标对象
private IUserDao target;
public UserDaoProxy(IUserDao target) {
this.target = target;
}
@Override
public void save() {
System.out.println("开启事务...");
//执行目标对象的方法(接口回调)
target.save();
System.out.println("提交事务...");
}
}
public class TestProxy {
/**
* 静态代理测试
*/
@Test
public void testStaticProxy() {
IUserDao target = new UserDao();
UserDaoProxy userDaoProxy = new UserDaoProxy(target);
System.out.println("静态代理userDaoProxy的class:" + userDaoProxy.getClass());
userDaoProxy.save();
}
}
2.JDK动态代理
动态代理也称为JDK代理,接口代理。动态代理借助于JDK的API实现,
Proxy类:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
ClassLoader loader:
指定当前目标对象使用的类加载器,获取加载器的方法是固定的Class<?>[] interfaces:
目标对象实现的接口的类型,使用泛型方式确认类型InvocationHandler h:
事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入特点:
1.代理对象不需要实现接口,但是目标对象要实现接口,否则不能使用JDK动态代理;
2.代理对象是动态生成的,通过JDK的API,动态地在内存中创建代理对象。
第一种,不实现接口InvocationHandler。
首先,定义Proxy工厂类。
public class ProxyFactory {
//维护一个目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/**
* 动态创建代理对象
*
* @return
*/
public Object getProxyInstance() {
// 指定目标对象使用的类加载器/目标对象的接口/事件处理器
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
/**
* 该方法invoke被执行几次?------- 看代理对象调用方法几次
* 代理对象调用接口相应方法 都是调用invoke
* @param proxy 代理对象
* @param method 目标方法的字节码对象
* @param args 调用目标方法时的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务...");
//运用反射执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务...");
return returnValue;
}
});
}
}
然后,使用工厂类
public class TestProxy {
/**
* JDK动态代理测试
*/
@Test
public void testDynamicProxy() {
IUserDao target = new UserDao();
// 第一种方式,ProxyFactory中的InvocationHandler是匿名类
System.out.println("target对象class:" + target.getClass());
ProxyFactory proxyFactory = new ProxyFactory(target);
System.out.println("jdk动态代理proxyFactory的class" + proxyFactory.getProxyInstance().getClass().getName());
}
」
第二种方式:实现接口InvocationHandler。
首先,实现InvocationHandler接口。
public class UserDaoInvocationHandler implements InvocationHandler {
/**
* 被代理的对象
*/
private Object target;
public UserDaoInvocationHandler(Object target) {
this.target = target;
}
/**
* 处理动态代理类上的所有方法调用
* 本调用处理器根据这三个参数 进行预处理或分派到委托类实例上「反射」执行
*
* @param proxy 代理类
* @param method 被调用的方法对象
* @param args 方法入参
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务...");
Object returnValue = method.invoke(target, args);
System.out.println("提交事务...");
return returnValue;
}
}
然后,使用Proxy.newProxyInstance(classLoader, interfaces, invocationHandler)
public class TestProxy {
/**
* JDK动态代理测试
*/
@Test
public void testDynamicProxy() {
IUserDao target = new UserDao();
// 第二种方式,实现InvocationHandler接口
InvocationHandler invocationHandler = new UserDaoInvocationHandler(target);
ClassLoader classLoader = target.getClass().getClassLoader();
Class[] interfaces = target.getClass().getInterfaces();
IUserDao userDao2 = (IUserDao) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
System.out.println("jdk动态代理对象userDao2的class:" + userDao2.getClass().getName());
userDao2.save();
}
}
3.Cglib代理
Cglib代理,也称为子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展。
特点:
1.代理对象和目标对象都不需要实现接口;
2.以目标对象子类的方式实现代理。
public class CglibProxyFactory {
//目标对象
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
/**
* 为目标对象创建一个代理对象
*
* @return 子类对象
*/
public Object getProxyInstance() {
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(new MethodInterceptor() {
/**
*
* @param object cglib生成的代理对象
* @param method 目标对象方法(被拦截的方法)
* @param objects 方法参数(被拦截方法的参数)
* @param methodProxy 代理方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开启事务...");
Object returnValue = methodProxy.invoke(target, objects);
System.out.println("提交事务...");
return returnValue;
}
});
//4.创建target类的子类(也是代理对象)
return en.create();
}
}
public class TestProxy {
/**
* CgLib动态代理测试
*/
@Test
public void testCglibProxy() {
UserDao target = new UserDao();
System.out.println("target对象class:" + target.getClass());
IUserDao proxy1 = (IUserDao) new CglibProxyFactory(target).getProxyInstance();
// 代理对象信息
System.out.println("cglib动态代理对象proxy1的class:" + proxy1.getClass().getName());
proxy1.save();
}
}