ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java动态代理

2020-02-21 23:54:48  阅读:203  来源: 互联网

标签:java Producer money 代理 proxy 动态 public


特点:字节码随用随创建,随用随加载
作用:不修改源码的基础上对方法进行增强
分类:

基于接口的动态代理

           * 涉及的类:Proxy
           * 提供者:JDK官方
        * 如何创建代理对象:
                使用Proxy类中的newProxyInstance方法
                    参数:
                        * ClassLoader:类加载器
                                用于加载代理对象字节码,和被代理对象使用相同的类加载器。
                                写法是固定的
                        * Class[]:字节码数组
                                用于让代理对象和被代理对象有相同的方法
                                写法也是固定的
                        * InvocationHandler:用于提供增强的代码
                                一般是写一个该接口的实现类,一般是匿名内部类,但是不是必须的.
                                此接口的实现类都是谁用谁写
        * 创建代理对象的要求:
            被代理类最少实现一个接口

实例
先定义一个接口
IProducer.java:

package com.jiading.proxy;

public interface IProducer {
    /*
    销售
     */
    public void saleProduct(Float money);
    /*
    售后
     */
    public void afterService(float money);
}

Producer.java

package com.jiading.proxy;
/*
一个生产者
 */
public class Producer implements IProducer{//代理必须是对实现了至少一个接口的对象进行
    /*
    销售
     */
    public void saleProduct(Float money){
        System.out.println("销售产品,并拿到钱:"+money);
    }
    /*
    售后
     */
    public void afterService(float money){
        System.out.println("提供售后服务并拿到钱:"+money);
    }

}

Client.java:

package com.jiading.proxy;

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

/*
模拟一个消费者
 */
public class Client {
    public static void main(String[] args) {
        final Producer producer = new Producer();
        IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(),
                new InvocationHandler() {
                    /*
                    执行被代理对象的任何接口方法都会结构该方法
                    方法参数的含义
                        proxy:代理对象的引用
                        method:当前执行的方法
                        args:当前执行方法所需的参数
                        return:和被代理对象有相同的返回值
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //提供增强的代码
                        Object returnValue = null;
                        //1.获取方法执行的参数
                        Float money = (Float) args[0];
                        //2.判断当前方法是不是销售
                        if ("saleProduct".equals(method.getName())) {
                            returnValue = method.invoke(producer, money*0.8f);
                        }
                        return returnValue;
                    }
                });
        proxyProducer.saleProduct(10000f);
    }
}

基于子类的动态代理

这种方法里类不需要继承接口,但是需要第三方库的支持

  • 涉及的类:Enhancer
    * 提供者:第三方cglib库
    * 如何创建代理对象:
    使用Enhancer类中的create方法
    参数:
    Class:字节码,用于指定被代理对象的字节码
    Callback:用于提供增强的代码
    一般写的是该接口的子接口的实现类,MethodInterceptor
    * 创建代理对象的要求:
    被代理类不能是最终类
    实例:
    pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>day03_proxy</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <packaging>jar</packaging>
<dependencies>
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.1_3</version>
    </dependency>

</dependencies>

</project>

Producer.java

package com.jiading.cglib;

import com.jiading.proxy.IProducer;

/*
一个生产者
 */
public class Producer {//代理必须是对实现了至少一个接口的对象进行
    /*
    销售
     */
    public void saleProduct(Float money){
        System.out.println("销售产品,并拿到钱:"+money);
    }
    /*
    售后
     */
    public void afterService(float money){
        System.out.println("提供售后服务并拿到钱:"+money);
    }

}

Client.java

package com.jiading.cglib;

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 Client {
    public static void main(String[] args) {
        final Producer producer = new Producer();
        Producer proxyProducer= (Producer)Enhancer.create(producer.getClass(), new MethodInterceptor() {
            /*
            执行被代理对象的任何方法都会经过该方法
            proxy,method和args和基于接口的代理方法中得到参数是一样的
            proxyMethod是当前执行方法的代理对象
             */
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                //提供增强的代码
                Object returnValue = null;
                //1.获取方法执行的参数
                Float money = (Float) args[0];
                //2.判断当前方法是不是销售
                if ("saleProduct".equals(method.getName())) {
                    returnValue = method.invoke(producer, money * 0.8f);
                }
                return returnValue;
            }
        });
        proxyProducer.saleProduct(10000f);
    }
}

关于为什么这里在内部类中能用到的局部变量必须是final修饰的,可以看这篇文章:https://www.cnblogs.com/dolphin0520/p/3811445.html

标签:java,Producer,money,代理,proxy,动态,public
来源: https://www.cnblogs.com/jiading/p/12343777.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有