本文介绍: 1)代理模式:为一个对象提供一个替身,以控制这个对象访问。即通过代理对象访问目标对象2)这样做的好处是:可以目标对象实现的基础上,增强额外功能操作,即扩展目标对象功能3)被代理对象可以远程对象创建开销大的对象需要安全控制的对象4)代理模式有不同的形式,主要有三种静态代理动态代理:JDK 代理接口代理Cglib 代理:可以在内存动态创建对象,而不需要实现接口,它是属于动态代理的范畴

介绍

案例准备

Calculator.java

package com.mcode.api.proxy;

/**
 * ClassName: Calculator
 * Package: com.mcode.api.proxy
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
/**
 * 目标接口
 */
public interface Calculator {
    int add(int a, int b);
}

CalculatorImpl.java

package com.mcode.api.proxy;

import com.mcode.api.proxy.Calculator;

/**
 * ClassName: CalculatorImpl
 * Package: com.mcode.api.proxy
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
/**
 * 目标对象
 */
public class CalculatorImpl implements Calculator {
    /**
     * 相加方法
     * @param a
     * @param b
     * @return
     */
    @Override
    public int add(int a, int b) {

        int result = a + b;

        System.out.println("方法内部 result = " + result);

        return result;
    }
}

静态代理

基本介绍

静态代理在使里时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现租同的接口或者继承和同父类—
应用实例

应用实例

核心代码

CalculatorStaticProxy.java

package com.mcode.api.proxy.staticproxy;

import com.mcode.api.proxy.Calculator;

/**
 * ClassName: CalculatorStaticProxy
 * Package: com.mcode.api.proxy.staticproxy
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
public class CalculatorStaticProxy implements Calculator {

    private Calculator target;


    public CalculatorStaticProxy(Calculator target) {
        this.target = target;
    }

    @Override
    public int add(int a, int b) {
        // 附加功能由代理类中的代理方法来实现
        System.out.println("[日志] add 方法开始了,参数是:" + a + "," + b);

        // 通过目标对象来实现核心业务逻辑
        int addResult = target.add(a, b);

        System.out.println("[日志] add 方法结束了,结果是:" + addResult);

        return addResult;
    }
}

调用代理

CalculatorTest.java

package com.mcode.api.proxy.staticproxy;

import com.mcode.api.proxy.CalculatorImpl;

/**
 * ClassName: CalculatorTest
 * Package: com.mcode.api.proxy.staticproxy
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
public class CalculatorTest {
    public static void main(String[] args) {
        //创建被代理对象
        CalculatorImpl calculator = new CalculatorImpl();
        //创建代理对象,聚合被代理对象
        CalculatorStaticProxy proxy = new CalculatorStaticProxy(calculator);
        //通过代理对象,调用被代理对象的方法
        proxy.add(1, 2);
    }
}

执行结果

image

静态代理优缺点

  • 1)优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展

  • 2)缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类

  • 3)缺点:一旦接口增加方法,目标对象与代理对象都要维护

动态代理

基本介绍

  • 1)代理对象不需要实现接口,但是目标对象要实现接口,否则不能用动态代理

  • 2)代理对象的生成,是利用 JDK 的 APl,动态的在内存构建代理对象

  • 3)动态代理也叫做:JDK 代理、接口代理

JDK 中生成代理对象的 API

1)代理类所在包:java.lang.reflect.Proxy

● 2)JDK 实现代理只需要使用 newProxyInstance 方法,但是该方法需要接收三个参数完整写法是:

static Object newProxylnstance(ClassLoader loader, Class<?&gt;[] interfaces, InvocationHandler h)

核心代码

ProxyFactory.java

package com.mcode.api.proxy.dynamic;

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

/**
 * ClassName: ProxyFactory
 * Package: com.mcode.api.proxy.dynamic
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */

/**
 *  代理工厂
 */
public class ProxyFactory {
    /**
     * 目标对象
     */
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxy() {

        /**
         * newProxyInstance():创建一个代理实例
         * 其中有三个参数:
         * 1、classLoader:加载动态生成的代理类的类加载器
         * 2、interfaces:目标对象实现的所有接口的class对象所组成的数组
         * 3、invocationHandler:设置代理对象实现目标对象方法的过程,即代理类中如何重写接口中的抽象方法
         */
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler invocationHandler = (proxy, method, args) -> {
            /**
             * proxy:代理对象
             * method:代理对象需要实现的方法,即其中需要重写的方法
             * args:method对应方法的参数
             */
            Object result = null;
            System.out.println("[动态代理][日志] " + method.getName() + ",参数:" + Arrays.toString(args));
            result = method.invoke(target, args);
            System.out.println("[动态代理][日志] " + method.getName() + ",结果:" + result);
            return result;
        };
        return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
    }
}

其中几个参数

调用代理

CglibProxyTest.java

package com.mcode.api.proxy.dynamic;

import com.mcode.api.proxy.Calculator;
import com.mcode.api.proxy.CalculatorImpl;

/**
 * ClassName: DynamicProxyTest
 * Package: com.mcode.api.proxy.dynamic
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
public class DynamicProxyTest {
    public static void main(String[] args) {
        //创建目标对象
        CalculatorImpl calculator = new CalculatorImpl();
        //通过代理工厂创建代理对象
        ProxyFactory proxyFactory = new ProxyFactory(calculator);
        //通过代理对象调用目标对象方法
        Calculator proxy = (Calculator)proxyFactory.getProxy();
        proxy.add(1,2);
    }
}

执行结果

image

Cglib 代理

基本介绍

实现步骤

核心代码

ProxyFactory.java

package com.mcode.api.proxy.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * ClassName: ProxyFactory
 * Package: com.mcode.api.proxy.cglib
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */

/**
 * 代理工厂
 */
public class ProxyFactory implements MethodInterceptor {

    /**
     * 目标对象
     */
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxy(){
        // 1、创建工具
        Enhancer enhancer = new Enhancer();
        // 2、设置父类
        enhancer.setSuperclass(target.getClass());
        // 3、设置回调函数,需要实现MethodInterceptor接口
        enhancer.setCallback(this);
        // 4、创建子类对象,即代理对象
        return enhancer.create();
    }

    /**
     *
     * @param o 代理对象
     * @param method 目标方法
     * @param args 目标方法参数
     * @param methodProxy 代理对象生成的代理方法
     * @return
     * @throws Throwable
     */
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object result = null;
        System.out.println("[cglib代理][日志] " + method.getName() + ",参数:" + Arrays.toString(args));
        result = method.invoke(target, args);
        System.out.println("[cglib代理][日志] " + method.getName() + ",结果:" + result);
        return result;
    }
}

调用代理

CglibProxyTest.java

package com.mcode.api.proxy.cglib;

import com.mcode.api.proxy.CalculatorImpl;

/**
 * ClassName: CglibProxyTest
 * Package: com.mcode.api.proxy.cglib
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
public class CglibProxyTest {
    public static void main(String[] args) {
        //创建目标对象
        CalculatorImpl calculator = new  CalculatorImpl();
        //通过代理工厂创建代理对象
        ProxyFactory proxyFactory = new ProxyFactory(calculator);
        //通过代理对象调用目标对象方法
        CalculatorImpl proxy = (CalculatorImpl)proxyFactory.getProxy();
        proxy.add(1,2);
    }
}

执行报错

Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InaccessibleObjectException-->Unable to make protected final java.lang.Class.

运行时增加 vm 环境变量

--add-opens java.base/java.lang=ALL-UNNAMED

执行结果

image

原文地址:https://blog.csdn.net/net_programmer1/article/details/134751759

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_49988.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注