Java 框架 Tips_02 — Spring中的动态代理(基于接口的动态代理、基于子类的动态代理)


欢迎访问笔者个人技术博客:http://rukihuang.xyz/

一、基于接口的动态代理(具有共同父接口)

1.1 如何常见代理对象

  • 使用Proxy类中的newProxyInstance()方法。

1.2 创建代理对象的要求

  • 被代理对象至少实现一个接口,如果没有则不使用。

1.3 newProxyInstance方法的参数

  1. ClassLoader:类加载器。用于加载代理对象字节码。和被代理对象使用相同的类加载器。固定写法
  2. Class[]:字节码数组。用于让代理对象和被代理对象具有相同的方法。固定写法
  3. InvocationHandler:用于提供增强的代码。如何代理。一般是该接口的实现类,通常为匿名内部类。

1.4 代码示例

1.4.1 被代理对象(实现了接口)

package com.ruki.service.impl;

import com.ruki.service.IPhoneProducer;

public class PhoneProducerImpl implements IPhoneProducer {

    public void sellPhone(final float money) {
        System.out.println("卖手机了" + money);
    }
}

1.4.2 测试

package com.ruki.test;

import com.ruki.service.IPhoneProducer;
import com.ruki.service.impl.PhoneProducerImpl;

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

public class PhoneTest {
    public static void main(String[] args) {
        final IPhoneProducer phoneService = new PhoneProducerImpl();
        IPhoneProducer proxyProducer = (IPhoneProducer) Proxy.newProxyInstance(
                phoneService.getClass().getClassLoader(),
                phoneService.getClass().getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        String name = method.getName();//获得方法名
                        Float payMoney = (Float) args[0];//获得顾客支付的价款
                        Object rtValue = null;//返回值
                        if ("sellPhone".equals(name)) {
                            //如果是卖手机
                            //没有2000块不卖
                            if (payMoney > 2000) {
                                rtValue = method.invoke(phoneService, payMoney / 2);
                            }
                        }
                        return rtValue;
                    }
                }
        );
        proxyProducer.sellPhone(4000f);
    }
}

二、基于子类的动态代理(代理继承被代理)

  • 需要使用第三方jar包,cglib

2.1 如何创建代理对象

  • 使用Enhancer类中的create()方法

2.2 创建代理对象的要求

  • 被代理对象不能是最终类,即不能被final修饰

2.3 create方法的参数

  1. class:字节码。指定被代理对象的字节码
  2. MethodInterceptor:拦截器指定如何代理

2.4 代码示例

2.4.1 被代理对象

package com.ruki.service.pojo;

public class PhoneProducerPojo {

    public void sellPhone(final float money) {
        System.out.println("卖手机了" + money);
    }
}

2.4.2 测试

package com.ruki.test;

import com.ruki.service.PhoneProducerPojo;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class PhoneTest2 {
    public static void main(String[] args) {
        final PhoneProducerPojo phoneProducer = new PhoneProducerPojo();//被代理

        PhoneProducerPojo cglibPhoneProducer = (PhoneProducerPojo) Enhancer.create(phoneProducer.getClass(), new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                String methodName = method.getName();//获得方法名
                Float money = (Float) args[0];//获得参数
                Object rtValue = null;//初始化返回值
                if ("sellPhone".equals(methodName)) {
                    if (money > 1000f) {
                        rtValue = method.invoke(PhoneProducerPojo, money / 2);
                    }
                }

                return rtValue;
            }
        });

        cglibPhoneProducer.sellPhone(2000f);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值