java 代理Proxy

本文详细介绍了Java中的静态代理和动态代理,动态代理通过InvocationHandler实现方法增强,解决了静态代理的局限性。同时,针对未实现接口的类,文章探讨了CGLIB库作为动态代理的替代方案,展示了CGLIB如何创建代理对象并实现方法拦截。这些代理技术在AOP(面向切面编程)和框架中广泛应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代理

代理的作用:对具有通用功能的方法进行增强。(把通用功能部分拿出来经行代理)

静态代理

package demo01;

/**
 * 静态代理,对现有的方法进行增强
 *
 */
public class TestStaticProxy {
    public static void main(String[] args) {
        Human man = new Human("情迷");
        MarryCompany marryCompany = new MarryCompany(man);
        marryCompany.getMarry();
    }
}

interface Marry {
    /**
     * 结婚接口
     */
    void getMarry();
}

class Human implements Marry{
    String name;

    public Human(String name) {
        this.name = name;
    }

    public void getMarry() {
        System.out.println(this.name + "要结婚啦!!!");
    }
}

class MarryCompany implements Marry{
    private Human targetMan;

    public MarryCompany(Human targetMan) {
        this.targetMan = targetMan;
    }

    public void getMarry() {
        before();
        targetMan.getMarry();
        after();
    }

    private void before(){
        /**
         * 前置通知
         */
        System.out.println("预订酒店,值班场地!");
        System.out.println("推送婚车,迎接新娘!");
        System.out.println("专业司仪,致祝福语!");


    }

    private void after(){
        /**
         * 后置通知
         */
        System.out.println("打扫场地,收取费用!");
    }
}

预订酒店,值班场地!
推送婚车,迎接新娘!
专业司仪,致祝福语!
情迷要结婚啦!!!
打扫场地,收取费用!

以上代码解决了对结婚方法的增强,但是未解决通用行,只能对Human进行代理,而不能对其他类的对象进行代理,解决办法,我们对代理类进行修改一下:
前面的代码是对类的代理,现在改为对Marry接口的代理,一样完成了代理,并且使得代理对象具有了通用性,代理类只需实现Marry接口,就可使用代理类。

class MarryCompany implements Marry{
    private Marry targetMan;

    public MarryCompany(Marry targetMan) {
        this.targetMan = targetMan;
    }

    public void getMarry() {
        before();
        targetMan.getMarry();
        after();
    }

    private void before(){
        /**
         * 前置通知
         */
        System.out.println("预订酒店,值班场地!");
        System.out.println("推送婚车,迎接新娘!");
        System.out.println("专业司仪,致祝福语!");
    }

    private void after(){
        /**
         * 后置通知
         */
        System.out.println("打扫场地,收取费用!");
    }
}

动态代理

静态代理局限性:只能对某一个接口中的一个方法经行代理,接口每增加一个方法,就要对新增的方法增加一个代理方法。对于不同的类或者接口,里面不同的通用方法,也要写相同数量的代理方法。此时用动态代理:
InvocationHandle

package demo02.services;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestMarry {


    private Object object;

    public TestMarry(Object object){
        this.object = object;
    }

    public TestMarry() {
    }

    private void before(){
        System.out.println("before");
    }

    private void after(){
        System.out.println("after");
    }

    /**
     * 动态代理方法
     * @return Object
     */
    public Object proxy(){
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        before();
                        Object invoke = method.invoke(object, args);
                        after();
                        return invoke;
                    }
                });
    }
}
package demo02.services;

import demo02.IMarry;
import demo02.impl.Marry;

public class TestProxy {
    public static void main(String[] args) {
        final IMarry human = new Marry();
        TestMarry testMarry = new TestMarry(human);
        IMarry proxy = (IMarry) testMarry.proxy();
        proxy.marry();
        proxy.cutMarr();
    }
}

代理类接收Object对象,对其两个方法经行代理。

cglib代理 (第三方)

在动态代理的方法中,有一个参数是获取代理对象的类实现的接口,那么对于没有实现接口的类,就无法进行动态代理。所以使用cglib进行代理。

package cglibProxy;

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 TestCglib implements MethodInterceptor {

    private Object object;

    public TestCglib(Object o) {
        this.object = o;
    }

    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.cglib工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(object.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();
    }

    /**
     * 代理方法
     * @param o
     * @param method
     * @param objects
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before");
        Object o1 = methodProxy.invoke(object, objects);
        System.out.println("after");
        return o1;
    }
}

package cglibProxy;

import demo02.IMarry;
import demo02.impl.Marry;

public class CglibProxy extends Thread  {
    @Override
    public void run() {
        System.out.println("runging");
    }

    public static void main(String[] args) {
        TestCglib testCglib = new TestCglib(new Marry().setName("xiaolu"));
        IMarry proxyInstance = (Marry) testCglib.getProxyInstance();
        proxyInstance.marry();
        proxyInstance.cutMarr();
    }
}

TestCglib testCglib = new TestCglib(new Marry().setName(“xiaolu”));只能传类,不能是接口
这样就解决了没有实现接口的类不能代理的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

情迷不是情谜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值