【JAVA基础】动态代理

动态代理

一、特点

1、JDK反射库java.lang.reflect中提供了InvocationHandler接口和Proxy类,以实现动态代理,具体使用Proxy中的newProxyInstance()方法创建一个代理,其中需要实现第三个参数InvocationHandler接口。

2、动态代理基于接口实现

二、动态代理四要素

1、真正需要代理的接口

2、实现接口方法的实现类

2、代理对象

3、利用代理调用方法

注意:

 1、代理需要增强的的方法都在接口里面,接口需要写在newProxyInstance()的第二个参数中

 2、我们使用代理调用方法,其实是调用InvocationHandler()里面的invoke()方法

 3、invoke()是一个回调方法,会使用反射调用对应方法

三、练习

尝试写一个生成代理的方法,并且通过代理调用方法

第一步:创建一个需要代理的接口

public interface UserMapper {
    public String song();
    public String dance(String name);
}

第二步:实现接口

import com.eva.mapper.UserMapper;

/**
 * UserEntity实体类
 */
public class UserEntity implements UserMapper {
    private String name;

    public String song(){
        return "正在唱歌";
    }
    public String dance(String name) {
        return this.name+"在跳"+name;
    }
    
    public UserEntity() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

第三步:写一个创建proxy代理对象的方法

import com.eva.entity.UserEntity;
import com.eva.mapper.UserMapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 创建代理的方法
 */
public class ProxyUtil {
    /*
     * 写一个静态方法用来创建代理对象
     * 注意点:
     * 1.newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h)中的三个参数代表什么
     * 参数一:用于指定用哪个类加载器,去加载生成的代理类 ProxyUtil.class.getClassLoader();
     * 参数二:需要代理的对象(接口),可能有多个,需要的是有一个数组类型 new Class[]{UserMapper.class}
     * 参数三:代理需要做的事,具体就是要代理哪些方法
     * new InvocationHandler(){
     *  public Object invoke(Object proxy, Method method, Object[] args){
     *      代理的方法都写在invoke方法里面,
     *      我们调用代理方法的时候,实际就是调用InvocationHandler()里面的invoke()方法
     *  }
     * }
     * */
    public static UserMapper createProxy(UserEntity userEntity) {
        UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{UserMapper.class},
                new InvocationHandler() {
                    /*
                     * invoke()是个回调函数,invoke()决定到底代理了哪些方法
                     * 当代理调用方法时,实际是调用invoke里面的方法
                     * */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        /*
                        * 参数一:proxy 代理对象
                        * 参数二:method 正在使用的代理方法
                        * 参数三:使用方法时传递的参数
                        * 返回值:代理的方法返回值
                        * */
                        return method.invoke(userEntity, args);
                    }
                }
        );
        return userMapper;
    }
}

第四步:创建一个测试类,来使用代理调用一下方法

import com.eva.entity.UserEntity;
import com.eva.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "e")
public class Test {
    public static void main(String[] args) {
        UserEntity userEntity = new UserEntity("甄嬛");
        UserMapper proxy = ProxyUtil.createProxy(userEntity);
        String dance = proxy.dance("惊鸿舞");
        log.debug("{}",dance);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值