代理对象和委托对象继承相同接口,并控制外部对委托对象的访问。
1. 静态代理: 代理类在编译期确定,需要针对为每个接口实现不同的代理。
接口(Human):
public interface Human{ public void eatFood(); }
委托类(HumanImpl):
public class HumanImpl implements Human{ public void eatFood(){ System.out.print("真香!"); } }
代理类(HumanProxy):
public class HumanProxy implements Human{ private Human human; public HumanProxy(Human human){ this.human = human; } public void eatFood(){ before(); human.eatFood(); after(); } }
2. JDK动态代理: 运行期生成代理类
在代理类和委托类之间生成中介类,该类实现 InvocationHandler 接口。对委托对象方法的调用会转到中介对象的invoke()方法中,method标识了调用哪一个方法(通过反射获取),args代表方法参数。
public class HumanDynamicProxy implements InvocationHandler{ //委托对象 private Human human; public HumanDynamicProxy(Human human){ this.human = human; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); // 使用反射 Object result = method.invoke(human, args); after(); return result; } }
测试代码:
public static void main(String[] args){ //委托对象 Human realHuman = new HumanImpl(); //中介 InvocationHandler handler = new HumanDynamicProxy(human); //动态代理,需要指定要的实现的接口,使用反射通过接口获取方法名,拼接出类的字符串再构造出代理类 Human proxy = (Human) Proxy.newProxyInstance(realHuman.getClass().getClassLoader(), realhuman.getClass().getInterfaces(), handler); //通过代理类,执行方法; proxy.eatFood();
3. CGLIB动态代理(委托类不需要实现某接口)
public class Man{ public void eatFood(){ System.out.print("真香"); } }
生成一个类似的中介类,实现MethodInterceptor接口,方法调用转发到该类的intercept()方法。
class ManMethodInterceptor implements MethodInterceptor{
private Man man;
public ManMethodInterceptor(Man man){
this.man = man;
}
@Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable{ before(); Object result = method.invoke(man, args); after(); return result; }
测试代码:
Enhancer enhancer = new Enhancer(); //指定委托目标 enhancer.setSuperclass(Man.class); //指定中介类 enhancer.setCallback(new ManMethodInterceptor()); //生成代理类 Man man = (Man) enhancer.create(); hello.eatFood();
参考:https://blog.csdn.net/a396901990/article/details/26015977