代理模式
静态代理
例子:火车售票点
//抽象主题
interface SellTickets{
void sell();
}
//目标类
class TrainStation implements SellTickets{
public void sell(){
System.out.println("火车站售票...");
}
}
//代理类
class ProxyPoint implements SellTickets{
private TrainStation trainStation=new TrainStation();
public void sell(){
System.out.println("代售点售票...");
trainSation.sell();
}
}
动态代理
jdk代理
public class JdkProxy {
private TrainStation station=new TrainStation();
public SellTickets getSellTickets(){
SellTickets proxy=(SellTickets) Proxy.newProxyInstance(
//类加载器,用于加载代理类
station.getClass().getClassLoader(),
new Class[]{SellTickets.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("sell")){
System.out.println("代售点收取费用(jdk)");
}
Object res=method.invoke(station,args);
return res;
}
}
);
return proxy;
}
public static void main(String[] args) {
JdkProxy jdkProxy=new JdkProxy();
SellTickets sellTickets = jdkProxy.getSellTickets();
sellTickets.sell();
System.out.println(sellTickets.toString());
}
}
生成的代理类
通过arthas查看类结构
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import proxy.SellTickets;
final class $Proxy0
extends Proxy
implements SellTickets {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("proxy.SellTickets").getMethod("sell", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchMethodError(noSuchMethodException.getMessage());
}
catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
}
public final void sell() {
try {
this.h.invoke(this, m3, null);
return;
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final boolean equals(Object object) {
try {
return (Boolean)this.h.invoke(this, m1, new Object[]{object});
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
return (String)this.h.invoke(this, m2, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
return (Integer)this.h.invoke(this, m0, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
cjlib代理
maven坐标:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</denpendency>
代码:
//目标类
class TrainStation {
public void sell(){
System.out.println("火车站售票...");
}
}
class CglibProxy implements MethodInterceptor {
private TrainStation station=new TrainStation();
public TrainStation getProxyObject(){
Enhancer enhancer=new Enhancer();
//设置父类
enhancer.setSuperclass(TrainStation.class);
//设置回调函数
enhancer.setCallback(this);
//生成代理对象
return (TrainStation)enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
if(method.getName().equals("sell")){
System.out.println("代售点收取费用(cglib)");
}
return method.invoke(station,objects);
}
}
public class Test {
public static void main(String[] args) throws Exception{
CglibProxy proxy=new CglibProxy();
TrainStation proxyObject = proxy.getProxyObject();
proxyObject.sell();
System.out.println(proxyObject.getClass());
System.in.read();
}
}
生成的代理类的代码
public class TrainStation$$EnhancerByCGLIB$$22573775
extends TrainStation
implements Factory {
private boolean CGLIB$BOUND;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static final Method CGLIB$sell$0$Method;
private static final MethodProxy CGLIB$sell$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$finalize$1$Method;
private static final MethodProxy CGLIB$finalize$1$Proxy;
private static final Method CGLIB$equals$2$Method;
private static final MethodProxy CGLIB$equals$2$Proxy;
private static final Method CGLIB$toString$3$Method;
private static final MethodProxy CGLIB$toString$3$Proxy;
private static final Method CGLIB$hashCode$4$Method;
private static final MethodProxy CGLIB$hashCode$4$Proxy;
private static final Method CGLIB$clone$5$Method;
private static final MethodProxy CGLIB$clone$5$Proxy;
public final void sell() {
MethodInterceptor methodInterceptor = this.CGLIB$CALLBACK_0;
if (methodInterceptor == null) {
TrainStation$$EnhancerByCGLIB$$22573775.CGLIB$BIND_CALLBACKS(this);
methodInterceptor = this.CGLIB$CALLBACK_0;
}
if (methodInterceptor != null) {
Object object = methodInterceptor.intercept(this, CGLIB$sell$0$Method, CGLIB$emptyArgs, CGLIB$sell$0$Proxy);
return;
}
super.sell();
}
代理模式的区别
1.jdk代理和cjlib代理的区别
cjlib代理基于字节码生成技术,底层是通过动态生成目标类的子类.对于final修饰的类和方法,不能使用cjlib进行代理.
jdk代理是基于反射技术实现,底层是通过生成对应接口的实现类,是通过接口进行代理.
若目标类有接口则使用jdk代理效率更高,反之使用cjlib代理.