代理模式大家应该清楚,接下来深入挖掘一下这种设计模式
静态代理
- 静态代理里面,代理类是确定的,也就是说我们需要一个普通类和一个代理类,代码如下
首先是一个接口Animal,有一个eat()方法
package org.example.proxy.Static;
public interface Animal {
void eat();
}
然后我们写一个实现类Cat
package org.example.proxy.Static;
public class Cat implements Animal{
@Override
public void eat() {
System.out.println("The cat is eating");
}
}
现在如果要生成一个类对象,应该使用new Cat()
,但是我希望借助一个代理,那么现在就通过一个代理类来访问对象
package org.example.proxy.Static;
public class StaticProxyAnimal implements Animal{
private final Animal animal;
public StaticProxyAnimal(Animal animal){
this.animal = animal;
}
@Override
public void eat() {
System.out.println("The cat is hungry");
animal.eat();
}
}
调用测试
package org.example.proxy.Static;
public class StaticProxyAnimalDemo {
public static void main(String[] args) {
Animal cat = new StaticProxyAnimal(new Cat());
cat.eat();
}
}
动态代理
- 动态代理有两种方式,一种是JDK,另一种是CGlib
JDK
- JDK的动态代理主要是通过实现
InvocationHandler
接口的invoke
方法创建自己的调用处理器;通过为Proxy
类指定ClassLoader
对象和一组interface
来创建动态代理;通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型;通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数输入 - JDK动态代理是面向接口的代理模式
package org.example.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TargetInvoker implements InvocationHandler {
private final Object target;
public TargetInvoker(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before jdk handles");
Object result = method.invoke(target, args);
System.out.println("after jdk handles");
return result;
}
}
CGLib
- 实现机制是生成目标类的子类,通过调用父类(目标类)的方法实现,在调用父类方法时在代理中进行增强。换句话说就是继承父类方法并重写父类方法达到生成代理类的目的。这样你就会知道如果父类是final的肯定是无法继承,如果父类方法是private的也没法重写
- 它最大的好处是可以为没有实现接口的类提供代理的实现,你可以在上面JDK动态代理的
Cat
类里面加上一个普通方法,尝试使用JDK动态代理来调用这个普通方法,你会发现报错 - 接下来使用CGLib来进行动态代理,核心是重写一个
MethodInterceptor
类的intercept方法
package org.example.proxy.CGLib;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class TargetInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before cglib");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("after cglib");
return result;
}
}
package org.example.proxy.CGLib;
import net.sf.cglib.proxy.Enhancer;
public class CGLibProxy {
public static Object getProxy(Class<?> cls){
Enhancer enhancer = new Enhancer();
// 设置类加载
enhancer.setClassLoader(cls.getClassLoader());
// 设置被代理类
enhancer.setSuperclass(cls);
// 设置方法拦截器
enhancer.setCallback(new TargetInterceptor());
// 创建代理类
return enhancer.create();
}
}
package org.example.proxy.Static;
public class Cat implements Animal{
@Override
public void eat() {
System.out.println("The cat is eating");
}
public void play(){
System.out.println("The cat is playing");
}
}
调用普通方法
package org.example.proxy.CGLib;
import org.example.proxy.Static.Animal;
import org.example.proxy.Static.Cat;
public class CGLibDemo {
public static void main(String[] args) {
Cat cat = (Cat) CGLibProxy.getProxy(Cat.class);
cat.play();// 新添加的普通方法
}
}
- 发现可以调用
有兴趣可以深入研究一下源码实现