静态代理
// 接口
interface ClothFactory {
void productCloth();
}
// 被代理类
class NikeClothFactory implements ClothFactory{
@Override
public void productCloth() {
System.out.println("我是被代理类-Nike工厂生产了一批衣服");
}
}
// 代理类
class ProxyFactory implements ClothFactory {
ClothFactory cf;
public ProxyFactory(ClothFactory cf) { // 创建代理类对象时,实际要传入被代理类的对象
this.cf = cf;
}
@Override
public void productCloth() {
System.out.println("代理类开始执行,收取代理费!");
cf.productCloth();
}
}
// 测试
public class TestStaticProxy {
public static void main(String[] args) {
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ProxyFactory proxy = new ProxyFactory(nikeClothFactory);
proxy.productCloth(); // 调用代理类的方法就行
}
}
缺点:
- 每一个接口都要写一个代理类,繁琐
- 每一个都要配对使用,麻烦
JDK动态代理
接口:
public interface Subject {
int action();
}
被代理类:
public class RealSubject implements Subject{
@Override
public int action() {
System.out.println("我是被代理类!");
return 10;
}
}
代理类工厂:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 代理类工厂类 - 需要实现JDK里面的InvocationHandler接口
public class ProxyFactory implements InvocationHandler {
Object obj; // obj是实现类接口的被代理类的对象声明
/**
* 给被代理类的对象实例化(这个方法名字随便写的)
* @param obj 被代理类
* @return 动态返回代理类的对象,这个动态返回的对象和被代理对象实现了同一个接口或者多个
*/
public Object blind(Object obj) {
this.obj = obj;
// newProxyInstance方法参数分别是:
// 类加载器来定义代理类,代理类实现的接口列表,调度方法调用的调用处理函数(传入InvocationHandler实现类)
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), this);
}
/**
* 当通过代理类的对象发起对被重写的方法的调用时,都会转化为对一下invoke对象的调用
* @return 接口中抽象方法的返回值+处理后代理类返回的值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 如果接口里面有多个方法,这里可以根据方法名(即method参数)进行判断,做出不同的扩展内容!!!
System.out.println("执行jdk代理中加上的扩展功能");
Object returnVal = method.invoke(obj, args);
return returnVal;
}
}
测试:
public class TestProxy {
public static void test01() {
// 1.创建被代理对象
RealSubject real = new RealSubject();
// 2.创建代理工厂,即创建实现InvocationHandler接口的类对象
ProxyFactory proxyFactory = new ProxyFactory();
// 3.调用blind方法,传入被代理类(RealSubject类对象),
// 动态返回一个实现了 和被代理类同样接口(Subject接口) 的代理类对象
Object obj = proxyFactory.blind(real); // 这里是Subject类型,可以强转一下
Subject sub = (Subject) obj; // 此时sub就是代理类的对象
Object returnVal = sub.action(); // 这个执行就会转到 InvocationHandler接口实现类 的的invoke()方法调用
System.out.println(returnVal);
}
// 去代理上面的那个静态的例子
public static void test02() {
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ProxyFactory proxyFactory = new ProxyFactory();
ClothFactory clothFactory = (ClothFactory) proxyFactory.blind(nikeClothFactory);
clothFactory.productCloth(); // 执行,代理类中订单扩展内容和被代理类的方法都被执行了
}
}
优点:只需要写一个通用的代理类就行了!!
缺点:目标对象需要有实现接口
CGLIB动态代理
依赖:
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.3</version>
</dependency>
被代理类(可以不用实现接口了,但被代理类不能使用final修饰):
public class RealSubject {
public int action() {
System.out.println("我是被代理类!");
return 10;
}
}
代理类工厂:
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 ProxyFactory implements MethodInterceptor {
private Object obj;
/**
* 传入被代理类,返回代理对象
* @param obj 被代理类
* @return 代理对象
*/
public Object blind(Object obj) {
this.obj = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass()); // 设置父类
enhancer.setCallback(this); // 设置回调方法
return enhancer.create(); // 创建子类对象,即代理对象
}
/**
* 当通过代理类的对象发起对要代理的方法的调用时,都会转化为对一下intercept()的调用
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("执行cglib代理中加上的扩展功能");
Object returnVal = method.invoke(obj, args);
return returnVal;
}
}
测试:
public class TestProxy {
public static void main(String[] args) {
// 1.创建被代理对象
RealSubject realSubject = new RealSubject();
// 2.创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
// 3.获取代理类
Object obj = proxyFactory.blind(realSubject);
RealSubject sub = (RealSubject) obj; // 这里是RealSubject类型,可以强转一下
Object returnVal = sub.action(); // 这个执行就会转到 MethodInterceptor接口实现类的的intercept()方法调用
System.out.println(returnVal);
}
}
优点:只需要写一个通用的代理类就行了,而且目标对象不需要有实现接口