前言
代理模式是GOF中的一种,指的是一个类代表另一个类的功能,这种类型的设计模式属于结构型模式。代理模式在java中运用的很多,AOP就是基于动态代理实现的。代理模式又分为静态代理和动态代理。
静态代理
若代理类在程序运行前就已经存在,那么这种代理模式就是静态代理。通常情况下,静态代理类和目标类都会实现同一个接口或者派生自相同父类。
创建接口和目标实现类
package com.fzxey.proxy;
//定义目标类和代理类的接口
public interface ITestService {
String doSome();
}
package com.fzxey.proxy.impl;
import com.fzxey.proxy.ITestService;
//实现接口
public class TestService implements ITestService {
@Override
public String doSome() {
return "hello";
}
}
代理类
package com.fzxey.proxy.impl;
import com.fzxey.proxy.ITestService;
//实现接口
public class TestProxy implements ITestService {
//定义接口类型变量
private ITestService target;
//利用构造函数设置
public TestProxy(ITestService target) {
this.target = target;
}
@Override
public String doSome() {
//增强目标类中的方法
return target.doSome().toUpperCase();
}
}
测试类
package com.fzxey.proxy;
import org.junit.Test;
import com.fzxey.proxy.impl.TestProxy;
import com.fzxey.proxy.impl.TestService;
public class ProxyTest {
@Test
public void test() {
ITestService ts = new TestService();
TestProxy tp = new TestProxy(ts);
System.out.println(tp.doSome());
}
}
结果
HELLO
动态代理
代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。
这里介绍两种动态代理方式:JDK动态代理(java自带的)和CGLIB动态代理(github开源项目)
JDK动态代理
java.lang.reflect.Proxy:生成动态代理类和对象;
java.lang.reflect.InvocationHandler(处理器接口):可以通过invoke方法实现
对真实角色的代理访问。
每次通过 Proxy 生成的代理类对象都要指定对应的处理器对象。
创建接口和目标实现类
package com.fzxey.proxy;
//定义目标类和代理类的接口
public interface ITestService {
String doSome();
}
package com.fzxey.proxy.impl;
import com.fzxey.proxy.ITestService;
//实现接口
public class TestService implements ITestService {
@Override
public String doSome() {
return "hello";
}
}
JDK代理实现
package com.fzxey.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.junit.Test;
import com.fzxey.proxy.impl.TestProxy;
import com.fzxey.proxy.impl.TestService;
public class ProxyTest {
@Test
//JDK动态代理测试
public void test1() {
//获取目标类对象
ITestService ts = new TestService();
//获取动态代理对象
ITestService its = (ITestService)Proxy.newProxyInstance(
//目标类的类加载器
ts.getClass().getClassLoader()
//目标类的实现的所有的接口
, ts.getClass().getInterfaces()
//处理器
, new InvocationHandler() {
/**
* proxy:代理对象
* method:目标的方法对象
* args:目标方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String msg = (String)method.invoke(ts, args);
return msg.toUpperCase();
}
});
System.out.println(its.doSome());
}
}
结果
HELLO
CGLIB动态代理
Cglib 动态代理是针对代理的类, 动态生成一个子类, 然后子类覆盖代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。
CGLIB作为一个开源项目,其代码托管在github,地址为:https://github.com/cglib/cglib
创建目标类
package com.fzxey.proxy.impl;
public class TestService implements ITestService {
@Override
public String doSome() {
return "hello";
}
}
CGLIB代理类
package com.fzxey.proxy;
import java.lang.reflect.Method;
import com.fzxey.proxy.impl.TestService;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private TestService target;
public CglibProxy(TestService target) {
this.target = target;
}
/**
* 创建cglib代理对象的方法
* @return
*/
public TestService createProxy() {
//创建增强器
Enhancer e = new Enhancer();
//指定父类
e.setSuperclass(TestService.class);
//指定回调接口对象
e.setCallback(this);
//创建cglib代理对象
return (TestService) e.create();
}
/**
* 拦截方法
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// TODO Auto-generated method stub
String msg = (String) method.invoke(target, args);
return msg.toUpperCase();
}
}
测试
package com.fzxey.proxy;
import org.junit.Test;
import com.fzxey.proxy.impl.TestProxy;
import com.fzxey.proxy.impl.TestService;
public class ProxyTest {
@Test
public void test3() {
TestService ts = new TestService();
TestService cp = new CglibProxy(ts).createProxy();
System.out.println(cp.doSome());
}
}
结果
HELLO
@Fzxey