栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java动态代理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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();
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/358205.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号