代理模式

静态代理

  • 用父亲帮儿子找对象来举例:
public interface Person {
    public void findLove();
}
public class Son implements Person {
    @Override
    public void findLove() {
        System.out.println("儿子要找一个对象");
    }
}

public class Father implements Person {
    private Son son;
    public Father (Son son){
        this.son = son ;
    }
    @Override
    public void findLove() {
        System.out.println("开始物色");
        son.findLove();
        System.out.println("找到");
    }
}
public class StaticProxyTest {
    public static void main(String[] args) {
        Father father = new Father(new Son());
        father.findLove();
    }
}

输出:

开始物色
儿子要找一个对象
找到

代 理对象持有被代理对象的引用,客户端调用代理对象方法,同时也调用被代理对象的方 法,但是在代理对象前后增加一些处理。这就是一个简单的静态代理。

动态代理:

public class Girl implements Person{
    @Override
    public void findLove() {
        System.out.println("女兒要找一个对象");
    }
}
public class JDKProxy implements InvocationHandler{
    private Object target;
    public Object getInstance(Object target){
        this.target = target;
        Class<?> clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始物色");
        Object invoke = method.invoke(this.target, args);
        System.out.println("找到");
        return invoke;
    }
}
public class JDKProxyTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//        Object instance = new JDKProxy().getInstance(new Girl());
//        Method method = instance.getClass().getMethod("findLove", null);
//        method.invoke(instance);
        //或者:
        Person instance =(Person) new JDKProxy().getInstance(new Girl());
        instance.findLove();
    }
}

CGLib方式


public class CGLibProxy implements MethodInterceptor {

    public Object getInstance(Class<?> clazz){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println("开始物色");
        Object object = methodProxy.invokeSuper(o, objects);
        System.out.println("找到");
        return object;
    }
}
public class CglibTest {
    public static void main(String[] args) {
        Girl instance = (Girl)new CGLibProxy().getInstance(Girl.class);
        instance.findLove();
    }
}
JDK动态代理的实现原理
  • 1、拿到被代理类的引用,并且获取它的所有的接口(反射获 取)。
  • 2、JDK Proxy类重新生成一个新的类,实现了被代理类所有 接口的方法。
  • 3、动态生成Java代码,把增强逻辑加入到新生成代码中。
  • 4、编译生成新的Java代码的class文件。
  • 5、再重新加载到 JVM 中运行。
CGLib 和 JDK 动态代理对比
  • 1.JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
  • 2.JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
  • 3.JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高。
代理模式与 Spring

ProxyFactoryBean 核心的方法就是 getObject()方法

public Object getObject() throws BeansException { initializeAdvisorChain(); if (isSingleton()) { return getSingletonInstance(); }else { if (this.targetName == null) { logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " + "Enable prototype proxies by setting the 'targetName' property."); }return newPrototypeInstance(); } }

在 getObject()方法中,主要调用 getSingletonInstance()和 newPrototypeInstance(); 在 Spring 的配置中,如果不做任何设置,那么 Spring 代理生成的 Bean 都是单例对象。 如果修改 scope 则每次创建一个新的原型对象。

Spring 中的代理选择原则
  • 1、当 Bean 有实现接口时,Spring 就会用 JDK 的动态代理
  • 2、当 Bean 没有实现接口时,Spring 选择 CGLib。
  • 3、Spring 可以通过配置强制使用 CGLib,只需在 Spring 的配置文件中加入如下代码:
    <aop:aspectj-autoproxy proxy-target-class=“true”/>

代理模式的优缺点

使用代理模式具有以下几个优点:
  • 1、代理模式能将代理对象与真实被调用的目标对象分离。
  • 2、一定程度上降低了系统的耦合度,扩展性好。
  • 3、可以起到保护目标对象的作用。
  • 4、可以对目标对象的功能增强。
缺点
  • 1、代理模式会造成系统设计中类的数量增加。
  • 2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
  • 3、增加了系统的复杂度。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值