精华内容
下载资源
问答
  • 动态代理的实现方式
    千次阅读
    2022-04-23 23:56:12

    Java 中,实现动态代理有两种方式:

    1、JDK 动态代理:java.lang.reflect 包中的 Proxy 类和 InvocationHandler 接口提供了生成动态代理类的能力。
    2、Cglib 动态代理:Cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。

    JDK 动态代理和 Cglib 动态代理的区别:

    JDK 的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用 CGLIB实现。
    Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 Java 类与实现 Java接口。它广泛的被许多 AOP 的框架使用,例如 Spring AOP 和 dynaop,为他们提供方法的 interception(拦截)。
    Cglib 包的底层是通过使用一个小而快的字节码处理框架 ASM,来转换字节码并生成新的类。不鼓励直接使用 ASM,因为它需要你对 JVM 内部结构包括 class 文件的格式和指令集都很熟悉。

    Cglib 与动态代理最大的区别就是:

    1. 使用动态代理的对象必须实现一个或多个接口。
    2. 使用 cglib 代理的对象则无需实现接口,达到代理类无侵入。
    更多相关内容
  • 主要介绍了Spring CGLlB动态代理实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 如何实现动态代理

    2022-04-06 16:03:31
    1.动态代理和静态代理的区别 静态代理:在编译之前就已经确定好代理对象,代理方法等等 动态代理:在编译后才明确代理对象以及代理方法等等 2.JDK代理原理 ...4.JDK实现动态代理 dao public in...

    1.动态代理和静态代理的区别

    静态代理:在编译之前就已经确定好代理对象,代理方法等等

    动态代理:在编译后才明确代理对象以及代理方法等等

    2.JDK代理原理

     使用JDK动态代理方法,我们需要代理类和被代理类同时继承同一个接口才能进行增强。

     3.CGlib代理原理

     JDK动态代理时,必须提供一个接口,但是在有些环境中,我们并不能提供一个接口,只能采用第三方的代理方法CGlib。它的优势是只要提供一个非抽象类,即可进行增强处理。

    4.JDK实现动态代理

    dao

    public interface UserDao {
        public void addUser();
        public void deleteUser();
    }
    

    daoImpl

    public class UserDaoImpl implements UserDao{
        @Override
        public void addUser() {
            System.out.println("添加用户");
        }
    
        @Override
        public void deleteUser() {
            System.out.println("删除用户");
        }
    }

    增强类

    public class MyAspect {
        public void check(){
            System.out.println("模拟检查权限~~");
        }
    
        public void log(){
            System.out.println("打印日志~~");
        }
    }
    

    JDK代理类

    继承实现InvocationHandler接口

    Proxy.newProxyInstance参数说明

    第一个参数 本类的类加载器

    第二个参数 被代理类实现的所有接口

    第三个参数 本类

    invoke方法中的参数说明

    proxy 被代理的对象

    method 将要被执行的方法信息(反射)

    args 执行方法需要的参数

    public class MyProxy implements InvocationHandler {
    
        private UserDao userDao;
    
        public Object createProxy(UserDao userDao){
            this.userDao = userDao;
            //1.本类的类加载器 2.被代理类实现接口 3.本类
            return Proxy.newProxyInstance(MyProxy.class.getClassLoader(),userDao.getClass().getInterfaces(),this );
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            MyAspect myAspect = new MyAspect();
            myAspect.check();
            Object invoke = method.invoke(userDao, args);
            myAspect.log();
            return invoke;
        }
    }

    测试代理方法实现

    public class JDKTest {
        public static void main(String[] args) {
            MyProxy myProxy = new MyProxy();
    
            UserDao userDao = new UserDaoImpl();
    
            UserDao userDao1 = (UserDao) myProxy.createProxy(userDao);
            userDao1.addUser();
            userDao1.deleteUser();
        }
    
    
    }
    

    5.CGLib实现动态代理

    dao

    public class UserDao {
        public void addUser(){
            System.out.println("添加用户");
        }
        public void deleteUser(){
            System.out.println("删除用户");
        }
    }
    

    增强类

    public class MyAspect {
        public void check(){
            System.out.println("模拟检查权限~~");
        }
    
        public void log(){
            System.out.println("打印日志~~");
        }
    }
    

    CGlib代理类

    注意引入的jar:import org.springframework.cglib.proxy.MethodInterceptor;

    继承实现MethodInterceptor

    inertcept参数说明

    o 根据指定父类形成代理对象

    method 拦截的方法

    objects 方法的参数

    methodProxy 方法的代理对象,用于执行父类方法

    public class CglibProxy implements MethodInterceptor {
    
        public Object createProxy(Object o){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(o.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            MyAspect myAspect = new MyAspect();
            myAspect.check();
            Object obj = methodProxy.invokeSuper(o,objects);
            myAspect.log();
            return obj;
        }
    }

    测试方法

    public class CglibTest {
        public static void main(String[] args) {
            CglibProxy cglibProxy = new CglibProxy();
            UserDao userDao = new UserDao();
    
            UserDao proxy = (UserDao) cglibProxy.createProxy(userDao);
            proxy.addUser();
            proxy.deleteUser();
        }
    }

    展开全文
  • 此资源为文章中《代理设计模式:静态代理和动态代理的理解、实现与区别(优缺点)》与《 AOP动态代理声明式的3种配置方式过程与区别》的案例代码,可下载参考学习。
  • AOP动态代理实现方式 前言 什么是aop? AOP(Aspect Oriented Programming),即面向切面编程,也就是把那些业务无关,但是又被业务模块所共同调用的逻辑或行为封装起来,便于减少系统的重复代码,降低模块之间的...

    AOP动态代理的实现方式

    前言

    什么是aop?

    AOP(Aspect Oriented Programming),即面向切面编程,也就是把那些业务无关,但是又被业务模块所共同调用的逻辑或行为封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
    使用场景:日志,权限,监控,事务,异常等。

    一、aop实现原理

    1.JDK动态代理: 代理的类必须实现一个接口

    2.CGLIB动态代理: 动态生成被代理类的子类

    JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口,核心是InvocationHandler接口和Proxy类

    CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的

    二、aop注意事项

    1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
    2、如果目标对象实现了接口,也可以强制使用CGLIB实现AOP
    3、如果目标对象没有实现接口,必须采用CGLIB的动态代理,spring会自动在两种模式之间转换
    4、不管哪一种方式都不能用private和final做修饰词

    注:JDK动态代理要比cglib代理执行速度快,但性能不如cglib好
    **

    三、使用步骤

    1、引入库

    在这里插入图片描述

    2、主要代码部分

    /**  
    * <p>Title: A.java</p>  
    * <p>Description: </p>  
    * <p>Copyright: Copyright (c) 2019</p>  
    * <p>Company: www.nosprings.com</p>  
    * @author liuhaibing
    * @date 2021年3月30日  
    * @version 1.0  
    */  
    package com.icss.aop;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import java.lang.reflect.*;
    import java.util.*;
    
    public class ProxyBeanFactory{
    
        //日志对象
        private static final Logger LOGGER = LoggerFactory.getLogger(ProxyBeanFactory.class);
    
        //声明被代理类对象
        private Object interfaceObj;
    
        public ProxyBeanFactory() {
        }
    
        /**
         * 返回代理对象
         */
        public <T> T getProxyBean(Object interfaceObj){
            this.interfaceObj = interfaceObj;
            return (T)  Proxy.newProxyInstance(interfaceObj.getClass().getClassLoader(), interfaceObj.getClass().getInterfaces(), new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    return invokeMethod(proxy, method, args);
                }
            });
        }
    
        public Object invokeMethod(Object proxy, Method method, Object[] args) throws Throwable {
            Object result;
            if (method.isAnnotationPresent(CustomBefore.class)) {
                CustomBefore customBefore = method.getAnnotation(CustomBefore.class);
                if (null != customBefore && customBefore.value().length > 0){
                    List<String> list = Arrays.asList(customBefore.value());
                    list.stream().forEach(e -> {
                        execute(e, method.getParameterTypes(), args);
                    });
                }
            }
    
            //执行主方法
            result = method.invoke(interfaceObj, args);
    
            if (method.isAnnotationPresent(CustomAfter.class)) {
                CustomAfter customAfter = method.getAnnotation(CustomAfter.class);
                if (null != customAfter && customAfter.value().length > 0){
                    List<String> list = Arrays.asList(customAfter.value());
                    list.stream().forEach(e -> {
                        execute(e, method.getParameterTypes(), args);
                    });
                }
            }
            return result;
        }
    
        /**
         * 执行方法
         * @param serviceName
         * @param args
         * @throws Exception
         */
        private void execute(String serviceName, Class<?>[] parameterTypes, Object[] args){
            String[] c = parseServiceName(serviceName);
            //获取类名和方法名
            String className = c[0];
            String methodName = c[1];
            try {
                //动态寻找类和方法
                Object o = Class.forName(className).newInstance();
                Method m = o.getClass().getMethod(methodName, parameterTypes);
                m.invoke(o, args);
            } catch (Exception e) {
                e.printStackTrace();
                LOGGER.error("serviceName:" + serviceName);
            }
        }
    
        /**
         * 解析serviceName
         * @param serviceName
         * @return
         */
        private String[] parseServiceName(String serviceName){
            String[] className = new String[2];
            int index = serviceName.lastIndexOf(".");
            if (index == -1){
                return null;
            }
    
            //获取类名和方法名
            className[0] = serviceName.substring(0, index);
            className[1] = serviceName.substring(index + 1);
            return className;
        }
    }
    
    
    

    **

    总结

    动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。是因为所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以我们只要在invoke方法中统一处理,就可以对所有被代理的方法进行相同的操作了。

    展开全文
  • 很多的连接池都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前所有的应用服务器取数据库连接的方式都是这种方式实现的。但是另外一个共同的问题是,它们同时不允许使用者显式的调用...
  • AOP动态代理实现方式

    2011-06-25 13:17:57
    AOP动态代理描述了Spring AOP中使用Java高级技术功能实现动态代理,为Spring IOC等高级开发实现了逻辑功能;
  • 熟悉代理模式的可以直接点击目录第二章,jdk动态代理实现原理,本文的精髓所在,通过这个例子,教大家如何去学习源码。 1. 定义 代理模式(Proxy Pattern) 是一个使用频率非常高的设计模式,其定义如下: Provide a ...
  • 动态代理的两种实现方式

    千次阅读 2021-07-18 11:31:44
    一,jdk动态代理:(下面说的构造器是个人理解比喻,不是构造方法) 首先需要知道一个类和一个接口Proxy,InvocationHandler 代理类建造方法 1.Proxy.newProxyInstance(ClassLoader loader,Class<?>[] ...

    一,jdk动态代理:(下面说的构造器是个人理解比喻,不是构造方法)

    首先需要知道一个类和一个接口Proxy,InvocationHandler

    代理类建造方法

    1.Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

    参数:ClassLoader loader:任意对象的类加载器 .getClass().getClassLoader()

    Class<?>[] interfaces:全部的接口,一般是接口实现类的实例.getClass().getInterfaces()

    InvocationHandler h:代理类的构造器对象

    代理类构造器

    2.InvocationHandler接口只有一个方法:

    Object invoke(Object proxy, Method method, Object[] args)

    参数:Object proxy:指被代理的对象。

    Method method:要调用的方法,一般固定语句使用method.invoke(代理对象类,参数).来调用需要调用的方法

    Object[] args:方法调用时所需要的参数

    我们需要的:

    1.代理类构造器(类,创造代理的工具)(InvocationHandler的实现类,其invoke方法参数为固定的,其中method的invoke方法不是此invoke方法。由Proxy类使用反射调用,我们不需要调用)

    2.代理类建造方法(方法,中介创建者):Proxy.newProxyInstance(代理接口的类加载器,代理接口,代理类构造器对象--就是1) 该方法可写在代理类构造器中

    3.接口(房子)

    4.实现接口的类 即被代理对象(房东)

    使用步骤:

    1.先创建代理类构造器(InvocationHandler接口的实现类),重写接口中invoke方法,

    其中method.invoke(被代理的对象,参数),来调用需要调用的方法。我们可以在此上下增强原方法的功能

    (就是代理对象被创建出来后,调用方法时,该method通过反射获取你的方法,可以method.getName()获取调用的方法名,使用method.invoke()调用该方法)

    2.可以将代理类建造方法Proxy.newProxyInstance写在代理类构造器中,封装为getProxy方法,返回Object类型代理对象,使用时强转类型,这时参数为(任意对象.class.getClassLoader,接口(两种写法,一种是直接写接口.class,一种是实现类.class.getInterfaces()),代理类构造器(this))

    public class ProxyInvocationHandler implements InvocationHandler {
        //被代理接口/对象
            private Object object;
            //测试是否为任意对象的类加载器都可以作为参数
            private User user = new User();
    
        //构造方法
        public ProxyInvocationHandler(Object object) {
            this.object = object;
        }
    
        public Object getProxy(){
                return Proxy.newProxyInstance(
                        user.getClass().getClassLoader(),
                        object.getClass().getInterfaces(),
                        this);
            }
            //反射方法,method可以获取被代理对象调用的方法,进行一些操作
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String name = method.getName();
                System.out.println("调用前,调用的方法为:"+name);
                Object res = method.invoke(object,args);
                System.out.println("调用后,调用的方法为:"+name);
            return res;
        }
    }

    3.测试类中

    a.创建被代理对象。

    b.创建代理类构造器,并将被代理对象传参给它。

    c.使用代理类构造器创建代理类,因为得到的是Object类型,所以需要强转类型。

    d.调用方法。

    public class Test {
        public static void main(String[] args) {
            //被代理对象
            landlord landlord = new landlord();
            //代理类构造器
            ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(landlord);
            //创建代理类
            Host host= (Host) proxyInvocationHandler.getProxy();
    
            host.sellHost();
        }
    }

    结果

    调用前,调用的方法为:sellHost

    房东卖房

    调用后,调用的方法为:sellHost

    Cglib动态代理

    Cglib是针对实现类来代理的,被代理者不需要实现接口,它对目标类生成一个子类,并覆盖其中的方法,以实现方法的增强。

    cglib的主要方法拦截接口 MethodInterceptor,需要用户自己实现:

    public interface MethodInterceptor extends Callback {
        Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
    }


    参数说明:

    前三个参数与jdk中InvocationHandler中的Invoke相同:

    Object var1:指被代理的对象。
    Method var2:要调用的方法 
    Object[] var3:方法调用时所需要的参数 

    MethodProxy var4: JDK的java.lang.reflect.Method类的代理类,可以实现对源对象方法的调用。后面的例子将会帮助理解。

    Enhancer:cglib主要的增强类,下面简单看下其中方法:

    setSuperclass: 设置被代理的对象。

    setCallback: 设置回调函数,一般为MethodInterceptor的实现类。

    creat: 创建一个代理对象,你可以直接使用创建的代理对象调用原本的方法。

    看个实例:

    public class MyCglibInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("----------before----"+method.getName());
            Object o1 = methodProxy.invokeSuper(o, objects);
            System.out.println("----------after----"+method.getName());
            return o1;
        }
    }


    之前说了,cglib是创建一个子类,并覆盖目标类方法,所以我们调用方法时,是使用methodProxy.invokeSuper()。我们在每个方法之前之后都输出一些语句。

    测试代码:

     

    MyCglibInterceptor myCglibInterceptor=new MyCglibInterceptor();
            Enhancer enhancer=new Enhancer();
            enhancer.setSuperclass(myInterface.getClass());
            enhancer.setCallback(myCglibInterceptor);
            MyInterface res = (MyInterface) enhancer.create();
            res.getName();
            res.getAge();


    结果:

    ----------before----getName
    tom
    ----------after----getName
    ----------before----getAge
    11
    ----------after----getAge

    参考文档:

    尚硅谷-Spring5框架最新版教程(idea版)_哔哩哔哩_bilibili

    【狂神说Java】Spring5最新完整教程IDEA版通俗易懂_哔哩哔哩_bilibili

    (3条消息) 动态代理-两种实现方式_wy9717的博客-CSDN博客_动态代理实现

    展开全文
  • 主要介绍了Java JDK动态代理实现原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 动态代理三种实现方式 静态代理 动态代理 jdk动态代理 cglib动态代理 jar包 静态代理 ​ 某个对象提供⼀个代理,代理⻆⾊固定,以控制对这个对象的访问。 代理类和委托类有共同的⽗类或 ⽗接⼝,这样在任何使...
  • 实现动态代理的两种方式: 第一种是JDK提供的基于接口的动态代理,要求被代理的类必须至少实现一个接口。 2. 第二种是第三方cglib提供的基于子类的动态代理,。至少要继承一个类。 我们这里 来讲解,动态代理,以及...
  • Java实现动态代理的两种方式。 相对来说cglib更加方便。可以实现实现接口的类(非final类)
  • SpringAop动态代理的两种实现方式

    千次阅读 2021-08-18 22:54:52
    Spring的面向切面编程也是基于动态代理实现的 静态代理:也就是自己手动创建的代理对象 动态代理:也就是在程序运行中通过配置参...1.JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用In
  • Spring学习(五):动态代理的两种实现方式(全网最容易懂) 前言 要学习SpringAOP之前,肯定要弄清楚什么是动态代理动态代理是怎样实现的,以及动态代理能解决什么问题。 一、什么是动态代理 1、字面意思,代理...
  • 动态代理实现原理

    千次阅读 2022-04-14 15:40:13
    首先,动态代理是代理模式的一种实现方式,代理模式除了动态代理还有静态代理,只不过静态代理能够在编译时期确定类的执行对象,而动态代理只有在运行时才能够确定执行对象是谁。代理可以看作是对最终调用目标的一个...
  • 需求大致如下:通过url传参的方式,让Nginx代理到不同的服务器 浏览器输入:http://127.0.0.1/remote?port=8081被代理到:http://192.168.108.2:8081
  • 主要介绍了Spring如何基于Proxy及cglib实现动态代理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 动态代理的两种方式

    千次阅读 2022-01-05 16:15:34
    动态代理的两种方式:JDK方式和cglib方式。 一.JDK方式,在这个方式中,需要目标对象,目标对象的接口,增强方法,三个类。 public interface TargetInterface { public void save(); } public class ...
  • spring动态代理实现方式

    千次阅读 2019-08-15 18:31:25
    java动态代理: 利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 cglib动态代理: 利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。 JDK...
  • cglib动态代理实现及其原理浅析

    千次阅读 2022-03-22 18:18:42
    JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的...
  • 使用动态代理实现AOP

    千次阅读 2018-12-29 15:14:59
    之后我又想到了一种方法,那就是动态代理,其实spring的AOP底层实现也是基于动态代理的,使用动态代理还有一点好处就是不需要引入任何的外部jar包,因为这是jdk本身就提供的功能。但是却有一个缺陷就是jdk的动态代理...
  • 一、基础概念 AOP:把一个类当中不重要的部分拆出去,做成一个...3、实现接口的抽象方法invoke(被代理的对象的方法其实都在invoke方法中被运行) 添加需要的内容 如果不想每个被代理的都强加代码,可以加上...
  • JAVA - 动态代理实现(接口实现)

    千次阅读 2019-10-08 15:50:24
    我们先介绍下动态代理: 通俗的讲就是代替厂家卖商品,厂家“委托”代理为其销售商品。 介绍下场景: 某某工厂生产商品, 代理商从工厂拿去产品,我们从代理商处购买产品,这时候代理商回收百分之二十利润 接...
  • 动态代理实现方法以及对象HooK

    千次阅读 2017-07-13 18:19:21
    上一篇文章里面已经把动态代理的作用以及实现方法分析了一下,很明显我们可以用HooK做很多事情,比如例子里面的代理做了拿了回扣和偷换行货这种肮脏龌龊的事情。在真正应用的时候我们可以做更多的事情,比如用户登录...
  • cglib是利用生成子类继承父类的方法实现动态代理 原理实例 首先构造父类Singer public class Singer { public void dance(){ System.out.println("跳舞"); } public void singing(){ System.out.println...
  • Java动态代理实现方式一:InvocationHandler Java动态代理实现方式二:CGLIB 用CGLIB实现Java动态代理的局限性 面试问题:Java里的代理设计模式(Proxy Design Pattern)一共有几种实现方式?这个题目很像孔乙己问...
  • 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能...下面我们讲讲jdk动态代理和cglib动态代理实现及区别 jdk动态代理...
  • 代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。其中代理类主要负责为委托类...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 394,828
精华内容 157,931
关键字:

动态代理的实现方式