java动态代理

代理就是将一个对象的方法进行增强,让方法更有丰富的内容。主要是解决在一个原来的业务逻辑上添加一些辅助性的信息,让业务逻辑更加完善丰富。


1.jdk自带的动态代理

只能进行接口的动态代理。静态代理只能代理一种接口实现的类。动态代理可以对实现任何接口的实现类进行代理。

同时可以代理一个接口中的所有方法。

public class ProxyFactory {
    //只能是有接口的类才能被代理
    //o:就是接口实现的实例Student()
    public Object getProxyIntenst(Object o){
        return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), new InvocationHandler() {
            //这部分一般情况下写成单独的类
            //如果代理方法中没有返回值,那么返回就是null
            //proxy:对应的代理类,基本用不上
            //method:是接口指定的方法
            //args:方法需要的参数
            //Object:实际方法返回的值
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("开始:代理增强信息");
                //o是实现接口的具体实现类
                method.invoke(o,args);
                System.out.println("结束:代理增强信息");
                return null;
            }
        });
    }
}
public static void main(String[] args) {
    IPerson iPerson = new Student("jizhou");
    ProxyFactory proxyFactory = new ProxyFactory();
    IPerson proxyIntenst = (IPerson)proxyFactory.getProxyIntenst(iPerson);
    proxyIntenst.doSometing();
}
  • 实现原理

    jdk是通过反射的方法进行动态代理类的生成,然后生成相应的代理对象。

    ①通过ProxyGenerator.generateProxyClass()方法实现代理类class字节码的生成,

    ②然后通过Proxy.defineClass0()本地方法将class字节码文件加载到jvm中,

    ③通过反射创建代理类对象

  • 动态生成的代理类

代理了所有的方法,包括tostring等相关方法,下边的代码只是显示了一个方法的实现。

# 通过ProxyGenerator.generateProxyClass()方法实现代理类class字节码,生成的代理类
public final class ProxyPerson extends Proxy implements IPerson {
    private static Method m3;
        static {
        try {
            m3 = Class.forName("org.example.pojo.IPerson").getMethod("doSometing");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
    public ProxyPerson(InvocationHandler var1) throws  {
        super(var1);
    }
    //关键代理方法 h就是InvocationHandler接口的实现
    public final void doSometing() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
}
  • 思考

    • 动态代理可以修改入参。mybatis框架生成的mapper就是动态代理生成的代理类。
    • 处理的代理业务和接口实现完全分离。
    • 代理对象任务执行的依旧是真是对象
    • 在框架中大量应用

2.CGlib实现的动态代理

能够实现对普通类的代理,不需要接口的实现即可完成类的代理。

//被代理的类
public class User {
    public void addInfo(){
        System.out.println("添加业务信息");
    }
}
//生成代理类的工厂
public class ProxyFactory implements MethodInterceptor {
    private Object target;

    public ProxyFactory(Object o){
        target = o;
    }
    
    //Enhancer生成代理类
    public Object getProxyInstance(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    //代理增强类
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理开始********");
        method.invoke(target,objects);
        System.out.println("代理开始********");
        return null;
    }
}
//使用
public static void main(String[] args){
    User user = new User();
    ProxyFactory proxyFactory = new ProxyFactory(user);
    User proxyInstance = (User)proxyFactory.getProxyInstance();
    System.out.println(proxyInstance.getClass());
    proxyInstance.addInfo();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值