Java动态代理使用(基于JDK的动态代理)

1.动态代理概念

  • 动态代理通过创建一个代理类,该类实现了目标对象所实现的接口,从而在调用目标对象的方法时,可以插入自定义的逻辑。

通俗点说:

        动态代理就是创建一个代理类,在代理类中调用被代理方法,并且在代理类进行一些加强操作。

        举个例子:你的电脑桌上有显示器、键盘和鼠标。你想让你的电脑桌看起来好看一些,但是不想动原有的东西,你可以在桌面新添加摆件、氛围灯等等,这样就可以在不更改原有布局的情况下进行修饰桌面。

2.动态代理的应用场景

  1. AOP(面向切面编程)

    • 动态代理是AOP的核心实现机制之一,用于在方法执行前后织入切面逻辑。
  2. 日志记录

    • 在不修改原有代码的情况下,为方法调用添加日志记录功能。
  3. 权限校验

    • 在方法调用前进行权限校验,确保只有具有相应权限的用户才能执行该方法。
  4. 事务管理

    • 在方法调用前开启事务,调用后提交或回滚事务,确保数据的一致性。
  5. 远程服务调用

    • 通过代理对象实现远程服务调用的透明化,隐藏底层的通信细节。

3.动态代理案例

1.创建一个BeatMonsters接口

BeatMonsters 接口表示玩家能够进行的操作

package com.example.demo.proxyPratice;

public interface BeatMonsters {
    /**
     * 攻击怪物
     * @return
     */
    public String attack();

    /**
     * 防御
     */
    public String def1();
}

2.创建一个Player 实体类实现 BeatMonsters接口

package com.example.demo.proxyPratice;

public class Player implements BeatMonsters{
    private String name;

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


    @Override
    public String attack() {
        System.out.println(this.name + "进行了攻击!");
        return "";
    }

    @Override
    public String def1() {
        System.out.println(this.name + "开始防御!");
        return "";
    }
}

3.创建一个代理类,代理BeatMonsters 接口(重点)

package com.example.demo.proxyPratice;

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

public class BeatMonsterProxy {
    public static BeatMonsters createBeatMonsterProxy(Player player){
        BeatMonsters proxy = (BeatMonsters) Proxy.newProxyInstance(BeatMonsterProxy.class.getClassLoader(),
                new Class[]{BeatMonsters.class},
                new InvocationHandler() {
                    /**
                     *
                     * @param proxy 代理实例,方法是在此实例上调用的
                     *
                     * @param method 与在代理实例上调用的接口方法对应的 {@code Method} 实例。
                     * 该 {@code Method} 对象的声明类将是声明该方法的接口,该接口可能是代理接口的超接口,
                     * 代理类通过继承获得该方法。
                     *
                     * @param args 包含传递给代理实例方法调用时的参数值的对象数组,
                     * 如果接口方法不接受参数,则为 {@code null}。
                     *
                     * @return 返回值
                     * @throws Throwable 抛出异常
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 在被代理类之前执行
                        if ("attack".equals(method.getName())) {
                            System.out.println("玩家A装备了钻石剑!");
                        }

                        //被代理的方法执行
                         method.invoke(player,args);

                        //被代理类之后执行
                        if ("attack".equals(method.getName())) {
                            System.out.println("玩家A成功摧毁目标!");
                        } else {
                            System.out.println("没有受到伤害!");
                        }

                        return null;
                    }
                });

        return proxy;
    }
}

 4.调用代理类,实现想要的结果

package com.example.demo;

import com.example.demo.proxy.BigStar;
import com.example.demo.proxy.ProxyUtils;
import com.example.demo.proxy.Star;
import com.example.demo.proxyPratice.BeatMonsterProxy;
import com.example.demo.proxyPratice.BeatMonsters;
import com.example.demo.proxyPratice.Player;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {

        Player proxy = new Player("玩家ss");
        BeatMonsters s = BeatMonsterProxy.createBeatMonsterProxy(proxy);
        s.attack();

    }

}

运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值