原接口与对象
ProducerInterface.java
public interface ProducerInterface
{
/*
* @Author chensy
* @Description //TODO 销售
* @Date 11:11 2019/4/22
* @Param [money]
* @return void
**/
void saleProduct(float money);
/*
* @Author chensy
* @Description //TODO 售后
* @Date 11:11 2019/4/22
* @Param [money]
* @return void
**/
void afterService(float money);
}
Producer.java
package com.itheima.proxy;/*
*@program: springDay03_user
*@description: 动态代理对象, 生产者
*@author: chensy
*@create: 2019-04-22 11:09
*/
public class Producer implements ProducerInterface
{
/*
* @Author chensy
* @Description //TODO 销售
* @Date 11:11 2019/4/22
* @Param [money]
* @return void
**/
public void saleProduct(float money){
System.out.println("销售产品,拿到钱 : " + money);
}
/*
* @Author chensy
* @Description //TODO 售后
* @Date 11:11 2019/4/22
* @Param [money]
* @return void
**/
public void afterService(float money){
System.out.println("提供售后服务,并拿到钱 :" + money);
}
}
1).基于接口的动态代理
涉及的类: Proxy
提供者: JDK官方
- 如何创建代理对象:
使用Proxy类中的newProxyInstance方法 - 创建代理对象的要求:
被代理类最少实现一个接口 - newProxyInstance方法的参数
ClassLoader : 类加载器
它是用于加载代理对象字节码. 和被代理对象使用相同的类加载器.
Class[]: 字节码数组
它是用于让代理对象和被代理对象有相同的方法
InvocationHandler: 用于提供增强的代码
它是让我们写如何代理. - 代理对象代码:
public class client { public static void main(String[] args) { final Producer producer = new Producer(); /* * @Author chensy * @Description //TODO 增强原对象功能 * @Date 12:40 2019/4/22 * @Param [args] * @return void **/ ProducerInterface proxyProducer = (ProducerInterface) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() { /* * @Author chensy * @Description 执行被代理对象的任何接口都会经过该方法 * @Date 12:41 2019/4/22 * @Param 1.proxy 代理对象的引用 * 2.method 当前执行的方法 * 3.args 当前执行的方法所需的参数 * * @return java.lang.Object **/ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object o = null; if(method.getName().equals("saleProduct")) { Float money = (Float) args[0]; o = method.invoke(producer, money * 0.8f); } return o; } }); //执行代理对象的函数 proxyProducer.saleProduct(1000f); } }
5.结果
结果发现, 没有修改原代码的情况下, 使输出的钱减少了
2).基于子类的动态代理
- 基于第三方jar包(cglib)
Maven坐标:
<dependency> <groupId>org.sonatype.sisu.inject</groupId> <artifactId>cglib</artifactId> <version>2.2.1-v20090111</version> </dependency>
- 涉及类: Enhancer
创建方法: Enhancer.create - 被代理的不能是最终类
- 代理代码:
public class client { public static void main(String[] args) { final Producer producer = new Producer(); Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() { /* * @Author chensy * @Description * @Date 12:49 2019/4/22 * @Param o: 代理对象的引用 * method: 当前执行的方法 * objects 当前执行的方法所需的参数 * methodProxy: 当前执行的方法的代理对象 * @return java.lang.Object **/ public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { Object object = null; if(method.getName().equals("saleProduct")) { Float money = (Float) objects[0]; System.out.println("经过代理对象前 Money=" + money); o = method.invoke(producer, money * 0.8f); } return o; } }); cglibProducer.saleProduct(1000f); } }
5. 结果:
同样得到相同的结果, 不过被代理的类并没有实现接口
6.Producer.java
public class Producer { /* * @Author chensy * @Description //TODO 销售 * @Date 11:11 2019/4/22 * @Param [money] * @return void **/ public void saleProduct(float money){ System.out.println("销售产品,拿到钱 : " + money); } /* * @Author chensy * @Description //TODO 售后 * @Date 11:11 2019/4/22 * @Param [money] * @return void **/ public void afterService(float money){ System.out.println("提供售后服务,并拿到钱 :" + money); } }