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

1.1 如何常见代理对象

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

1.2 创建代理对象的要求

  • 被代理对象至少<font color="red">实现一个接口</font>,如果没有则不使用。

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 创建代理对象的要求

  • 被代理对象<font color="red">不能是最终类</font>,即不能被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);
    }
}
Last modification:September 27th, 2019 at 09:43 am