动态代理和静态代理区别和实现

代理模式应用场景:
生活中的租房中介、售票黄牛、婚介、经纪人、快递、事务代理、非侵入式日志监听等,都是代理模式的实际体现
代理模式主要有两个目的:一是保护目标对象,二是增强目标对象
静态代理举例:
首先创建代理主题角色ISubject类:

public interface ISubject { void request(); }

创建真实主题角色RealSubject类:

public class RealSubject implements ISubject {
public void request() { System.out.println("real service is called."); }
}

创建代理主题角色Proxy类:

public class Proxy implements ISubject {
private ISubject subject;
public Proxy(ISubject subject){
	 this.subject = subject; 
}
public void request() { 
	before(); 
	subject.request(); 
	after();
 }
public void before(){ 
System.out.println("called before request().");
 }
public void after(){ 
System.out.println("called after request().");
 }
}

客户端调用代码:

public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject()); proxy.request();
}

上面这个静态代理有个弊端就是Proxy只能接受ISubject类型的,万一业务扩张怎么办,而且每次都要去改代理类,就很麻烦,所以就有了动态代理:

动态代理的底层实现一般不用我们自己亲自去实现,已经有很多现成的API。在Java生态中,目前最普遍使用的是JDK自带的代理和Cglib提供的类库。下面我们首先基于JDK的动态代理支持如来升级一下代码。
首先,创建媒婆(婚介所)类JdkMeipo:

package proxy.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class MeiPoProxy implements InvocationHandler{

    private IPerson person;

    public IPerson getInstance(IPerson person){
        this.person = person;
        Class<?> clazz = person.getClass();
        return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);

    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("开始寻找对象!");
        method.invoke(this.person,args);
        System.out.println("寻找对象完毕!");
        return null;
    }
}

再创建一个类ZhaoLiu:

package proxy.dynamicProxy;

public class Zhangsan implements IPerson {

    public void findlove() {
        System.out.println("张三要求:肤白貌美大长腿!");
    }
}

测试代码如下:

package ProxyTest;

import proxy.dynamicProxy.MeiPoProxy;
import proxy.dynamicProxy.Zhangsan;

public class dynamicProxyTest {
    public static void main(String[] args) {
        MeiPoProxy meiPoProxy = new MeiPoProxy();
        meiPoProxy.getInstance(new Zhangsan()).findlove();
    }
}

在这里插入图片描述
CGlib动态代理的例子:
创建一个MeiPoProxy代理类:

package proxy.dynamicProxy.CglibProxy;

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 MeiPoProxy implements MethodInterceptor{

    public Object getInstance(Class<?> clazz){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);

        return enhancer.create();
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("开始");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("结束");
        return result;
    }
}

三张这块类可以不用实现任何接口:

package proxy.dynamicProxy.CglibProxy;

public class Zhangsan{

    public void findlove() {

        System.out.println("找对象要求:肤白貌美大长腿!");
    }
}

测试如下:

package ProxyTest;

import proxy.dynamicProxy.CglibProxy.MeiPoProxy;
import proxy.dynamicProxy.CglibProxy.Zhangsan;

public class CglibProxyTest {
    public static void main(String[] args) {
        MeiPoProxy meipoProxy = new MeiPoProxy();
        Zhangsan zhangsan = (Zhangsan) meipoProxy.getInstance(Zhangsan.class);
        zhangsan.findlove();
    }
}

在这里插入图片描述
动态代理和静态代理的区别:
静态代理属于硬编码,不灵活,不能做到适配性,如果需要代理的类很多,就没办法实现代理。动态代理是分为JDK和CGlib两种api方式代理,他们底层实现原理都是在内存中生成一个Proxy的类。JDK是实现了接口的方式,所以需要代理的类必须要实现接口,而CGlib是通过继承的方式,拿到了父类的所有方法属性,所以CGlib可以直接传入类的字节码信息就可以完成代理。Cglib还有一个不足之处就是不能有final修饰的方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值