一、 什么是代理
先说一下本篇只讲简单的使用例子,原理请看后面的文章
举个例子:比如你想买一辆车,但是买车需要去车管所上牌走各种手续验车等,你嫌太麻烦,可以找个代理人员帮你搞定,你付款给4s店,他开车去上牌都办妥之后把车开到你家楼下教给你,完活。这就是代理模式是不是很简单呢。
二、java中的代理
java中代理分为静态代理和动态代理,动态代理一般常用的又分为jdk动态代理和cglib动态代理,下面我们分别演示一下
jdk动态代理基于接口,动态生成实现了被代理类接口的类,如果没有实现接口则不能用jdk动态代理
cglib代理是基于继承的方式,动态生成被代理类的子类。
三、静态代理
还用一中买车的例子:直接上代码
//定义一个买车接口
public interface BuyCar {
void buyCar();
}
//自己买车的实现类
public class MySelfBuyCar implements BuyCar {
@Override
public void buyCar() {
System.out.println("自己出钱买奔驰");
}
}
//代理帮买车并上牌
public class ProxyBuyCar implements BuyCar {
private MySelfBuyCar mySelfBuyCar;
public ProxyBuyCar(MySelfBuyCar mySelfBuyCar) {
this.mySelfBuyCar = mySelfBuyCar;
}
@Override
public void buyCar() {
//钱还是得自己出的,代理又不傻====
mySelfBuyCar.buyCar();
System.out.println("代理帮你上牌---手续费+500");
}
public static void main(String[] args) {
BuyCar buyCar = new ProxyBuyCar(new MySelfBuyCar());
buyCar.buyCar();
}
}
运行main函数打印结果:
自己出钱买奔驰
代理帮你上牌---手续费+500
四、JDK动态代理
jdk动态代理是基于接口的代理模式,利用反射,自定handler需要实现java.lang.reflect.InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JdkProxyBuyCar implements InvocationHandler {
private Object object;
public JdkProxyBuyCar(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
try {
method.invoke(object,args);
System.out.println("帮你上牌---手续费+500");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
方法测试
public static void main(String[] args) {
Class<MySelfBuyCar> clazz = MySelfBuyCar.class;
JdkProxyBuyCar jdkProxyBuyCar = new JdkProxyBuyCar(new MySelfBuyCar());
BuyCar buyCar = (BuyCar)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), jdkProxyBuyCar);
buyCar.buyCar();
}
结果:
自己出钱买奔驰
代理帮你上牌---手续费+500
五、cglib动态代理
cglib代理是自动生成被代理类的子类实现的。
//引入cglib所需的jar包
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.9</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>7.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyBuyCar implements MethodInterceptor {
public Object getProxy(Class<?> clzss) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clzss);
// 设置回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// Object result = method.invoke(object, args); //死循环,内存溢出
// Object result = methodProxy.invoke(object, args);//死循环,内存溢出,具体为什么不能这么写需要看源码
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("代理买车---手续费+500");
return result;
}
}
方法测试:
public class Test {
public static void main(String[] args) {
CglibProxyBuyCar cglibProxyBuyCar = new CglibProxyBuyCar();
MySelfBuyCar proxy = (MySelfBuyCar)cglibProxyBuyCar.getProxy(MySelfBuyCar.class);
proxy.buyCar();
}
}
结果:
自己出钱买奔驰
代理帮你上牌---手续费+500
spring中的代理如果类实现了接口默认使用jdk动态代理,如果没有实现接口则使用cglib
本篇介绍了代理模式的基本使用