精华内容
下载资源
问答
  • jdk代理
    千次阅读
    2020-03-15 14:05:29
    一、JDK代理与CGLib代理区别

    1、JDK代理:
    只能对实现了接口的类生成代理,而不能针对类。

    2、CGLib代理:
    针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法(继承),因为是继承,所以该类或方法最好不要声明成final, 对于final类或方法,是无法继承的。

    3、何时使用JDK代理与CGLib代理?
    ①目标对象实现了接口,默认采用JDK代理实现AOP,此时可以强制使用CGLib代理实现AOP。
    ②目标对象没有实现了接口,必须强制使用CGLib代理实现AOP。

    4、如何强制使用CGLib代理实现AOP?
    ①添加CGLib库。
    ②在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

    二、举例

    1、接口IComputerService.java:

    package com.jd.computer.service;
    
    public interface IComputerService {
    
    	int div(int a, int b);
    }
    

    2、接口实现类ComputerService.java:

    package com.jd.computer.service;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class ComputerService implements IComputerService {
    
    	public int div(int a, int b) {
    		return a/b;
    	}
    }
    

    3、MethodAOP.java:

    package com.jd.aop;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.Signature;
    
    public class MethodAOP {
    
    	public void before(JoinPoint jp) {
    		Object [] args = jp.getArgs();
    		Signature signature = jp.getSignature();
    		String name = signature.getName();
    		System.out.println("The "+name+" method begins.");
    		System.out.println("The "+name+" method params ["+args[0]+","+args[1]+"].");
    	}
    }
    

    4、String配置文件application.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:util="http://www.springframework.org/schema/util"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
    		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
    		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
    
    	<context:component-scan base-package="com.jd"></context:component-scan>
    	
    	<bean class="com.jd.aop.MethodAOP" id="ma"></bean>
    	
    	<aop:config>
    		<aop:pointcut expression="execution(public int com.jd.computer.service.ComputerService.*(..))" id="pc"/>
    		<aop:aspect ref="ma">
    			<aop:before method="before" pointcut-ref="pc"/>
    		</aop:aspect>
    	</aop:config>
    	
    	<!-- proxy-target-class默认为false,使用JDK代理,为true时使用CGLib代理 -->
    	<aop:aspectj-autoproxy proxy-target-class="false"/>
    </beans>
    

    5、测试类Test.java:
    ①使用JDK代理,<aop:aspectj-autoproxy proxy-target-class="false"/>

    package com.jd.test;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.jd.computer.service.IComputerService;
    
    public class Test {
    
    	public static void main(String[] args) {
    		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
    		//JDK代理,getBean()中必须是接口IComputerService.class,不能是目标类ComputerService.class。
    		IComputerService computerService = applicationContext.getBean(IComputerService.class);
    		Class clazz = computerService.getClass();
    		//JDK代理:代理类和目标类没有继承关系,clazz.getSuperclass().getName()得到父类的类名
    		System.out.println(clazz.getSuperclass().getName());
    		applicationContext.close();
    	}
    }
    

    输出如下,可以看出此时运用JDK代理,没有继承关系:

    java.lang.reflect.Proxy
    

    ②使用CGLib代理,<aop:aspectj-autoproxy proxy-target-class="true"/>,

    package com.jd.test;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.jd.computer.service.ComputerService;
    import com.jd.computer.service.IComputerService;
    
    public class Test {
    
    	public static void main(String[] args) {
    		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
    		//CGLib代理,getBean()可以是接口IComputerService.class或者目标类ComputerService.class
    		IComputerService computerService = applicationContext.getBean(ComputerService.class);
    		Class clazz = computerService.getClass();
    		//CGLib代理:代理类继承自目标类
    		System.out.println(clazz.getSuperclass().getName());
    		applicationContext.close();
    	}
    }
    

    输出如下,可以看出运用CGLib代理,有继承关系:

    com.jd.computer.service.ComputerService
    
    更多相关内容
  • JDK代理和cglib代理

    2021-09-11 11:39:01
    静态代理JDK静态代理,而动态代理分为JDK动态代理和cglib动态代理。在Spring的AOP实现中,主要应用了JDK动态代理以及CGLIB动态代理。本篇文章中讲述JDK动态代理和cglib动态代理代理一般就是给被目标的类 ...

    Java中代理模式有两种:动态代理和静态代理。静态代理有JDK静态代理,而动态代理分为JDK动态代理和cglib动态代理。在Spring的AOP实现中,主要应用了JDK动态代理以及CGLIB动态代理。记录一下今天学习的收获。
    代理一般就是给目标类的方法在执行之前处理消息,过滤消息,也就是通常说的增强目标类的方法。之后还能进行消息的后置处理。代理类类本身不实现服务,而是通过调用真实目标类中的方法来提供服务。

    JDK静态代理源码的实现:

    1、业务接口:

    package com.static_agent;
    public interface TargetInterface {
        public void addBook();
    }
    
    

    2、业务实现:

    package com.static_agent;
    
    public class Target implements TargetInterface {
        @Override
        public void addBook() {
            System.out.println("增加一本图书成功------");
        }
    }
    

    3、代理类:

    package com.static_agent;
    
    public class Proxy implements TargetInterface{
        //真实目标对象
        private Target target;
        public Proxy(Target target) {
            this.target = target;
        }
    
        @Override
        public void addBook() {
            System.out.println("代理类方法,进行了增强。。。");
            System.out.println("事务开始。。。");
            // 调用目标类的方法;
            target.addBook();
            System.out.println("处理结束。。。");
        }
    }
    
    

    4、测试代码:

    package com.static_agent;
    
    public class StaticProxyTest {
        public static void main(String[] args) {
            //创建真实对象
            Target target = new Target();
            //创建代理对象
            Proxy proxy = new Proxy(target);
            //使用代理对象进行方法的执行
            proxy.addBook();
    
        }
    }
    
    

    5、执行结果
    在这里插入图片描述

    JDK动态代理源码的实现

    1、业务接口:

    package com.dynamic_agent;
    public interface TargetInterface {
        public void save();
    }
    
    

    2、业务实现:

    package com.dynamic_agent;
    public class Target implements TargetInterface {
        @Override
        public void save() {
            System.out.println("save Running-----");
        }
    }
    
    

    3、增强实现类:

    package com.dynamic_agent;
    public class Advice {
        public void before(){
            System.out.println("前置增强--------");
        }
    
        public void afterReturning(){
            System.out.println("后置增强--------");
        }
    }
    
    
    

    4、测试代码:

    package com.dynamic_agent;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class DynamicProxyTest {
        public static void main(String[] args) {
            //创建目标对象
            Target target = new Target();
            //增强对象
            Advice advice = new Advice();
    
            //返回值就是动态代理生成的对象
            /*        目标对象和代理对象是兄弟关系,俩都是接口的子类*/
    
            TargetInterface proxy= (TargetInterface) Proxy.newProxyInstance(
                    target.getClass().getClassLoader(), //目标对象类加载器
                    target.getClass().getInterfaces(),//目标对象相同的接口字节码对象数组
                    new InvocationHandler() {
                        //调用代理对象的任何方法,实质执行的都是  invoke()  方法
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //前置增强
                            advice.before();
                            //执行目标方法
                            Object invoke = method.invoke(target, args);
                            //后置增强
                            advice.afterReturning();
                            return invoke;
                        }
                    }
            );
    
            //调用代理对象的方法
            proxy.save();
            //以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
            System.out.println(proxy.getClass().getName());
        }
    }
    
    
    

    5、执行结果
    在这里插入图片描述

    cglib动态代理源码的实现

    1、导入依赖:

    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
    	<version>5.3.6</version>
    </dependency>
    
    

    2、目标类:

    package com.dynamic_cglib;
    public class Target{
    
        public void save() {
            System.out.println("cglib save Running-----");
        }
    }
    
    
    

    3、增强实现类:

    package com.dynamic_cglib;
    public class Advice {
        public void before(){
            System.out.println("cglib 前置增强--------");
        }
    
        public void afterReturning(){
            System.out.println("cglib 后置增强--------");
        }
    }
    
    
    

    4、测试代码:

    package com.dynamic_cglib;
    
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class DynamicCglibProxy {
        public static void main(String[] args) {
            //创建目标对象
            Target target = new Target();
            //增强对象
            Advice advice = new Advice();
    
            //返回值就是动态代理生成的对象  基于cglib
            //1、创建一个增强器
            Enhancer enhancer = new Enhancer();
            //2、设置父类(目标类)
            enhancer.setSuperclass(target.getClass());
            //3、设置回调函数
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    advice.before();//前置
                    Object invoke = method.invoke(target, args);//执行目标
                    advice.afterReturning();//后置
                    return invoke;
                }
            });
            //4、创建代理对象
            Target proxy = (Target) enhancer.create();
            proxy.save();
            System.out.println(proxy.getClass().getName());
        }
    
    }
    
    
    

    5、执行结果
    在这里插入图片描述

    关于动态代理总结:1、原理

    jdk静态代理直接是代理类实现目标对象的接口,完成代理,耦合度较高。

    jdk动态代理是接口代理,目标接口需要有一个类来实现自己的抽象方法,代理类和目标类是兄弟关系。

    jdk动态代理会根据目标对象生成一个代理类,并实现了该业务接口的jdk代理类,该类的字节码会被传进去的ClassLoader加载,创建了jdk代理对象实例,
    

    jdk代理对象实例在创建时,业务代理对象实例会被赋值给Proxy类,jdk代理对象实例也就有了业务代理对象实例,同时jdk代理对象实例通过反射根据被代理类的业务方法创建了相应的Method对象m(可能有多个)。当jdk代理对象实例调用业务方法,如proxy.saver();这个会先把对应的m对象作为参数传给invoke()方法(就是invoke方法的第二个参数),调用了jdk代理对象实例的invoke()回调方法,在invoke方法里面再通过反射来调用被代理对象的因为方法,也就是Object invoke = method.invoke(target, args);。

    cglib动态代理是继承代理,通过ASM字节码框架修改字节码生成新的子类,重写并增强方法的功能。

    2、优缺点

     jdk静态代理类只能为一个被代理类服务,如果需要代理的类比较多,就会出现代码冗余的问题。jdk静态代理在编译时产生class文件,运行时无需产生,可直接使用,效率好。
    
     jdk动态代理必须实现接口,通过反射来动态代理方法,消耗系统性能。但是无需产生过多的代理类,避免了重复代码的产生,系统更加灵活。
    
     cglib动态代理无需实现接口,通过生成子类字节码来实现,比反射快一点,没有性能问题。但是由于cglib会继承被代理类,所以被代理类不能是final类,被代理方法不能是final,并且会带着一点侵入性。
    

    因此,cglib的应用更加广泛一点。

    展开全文
  • NULL 博文链接:https://wuhuajun.iteye.com/blog/1926731
  • Spring中AOP底层的实现是基于动态代理进行实现的。 常见的动态代理技术有两种:JDK的动态代理和CGLIB。 两者的区别如下所示: 1、JDK动态代理只能对实现了接口的...1、当bean实现接口时,会用JDK代理模式 2、当bea

    Spring中AOP底层的实现是基于动态代理进行实现的。

    常见的动态代理技术有两种:JDK的动态代理和CGLIB。

    两者的区别如下所示:

    1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类

    2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法进行增强,但是因为采用的是继承,所以该类或方法最好不要声明为final,对于final类或方法,是无法继承的。

    Spring如何选择是用JDK还是cglib?

    1、当bean实现接口时,会用JDK代理模式

    2、当bean没有实现接口,会用cglib实现

    3、可以强制使用cglib

    源码解析:

    底层源码采用

    @EnableAspectJAutoProxy

    @ConditionalOnProperty

    两种方式来判别采用动态代理的方式,因为在类上标明了matchIfMissing = true,那就证明AOP是肯定会使用动态代理的,

    CJlib和JDK的具体采用哪个来代理,首先是根据proxyTargetClass,判别被代理类是否和代理目标类之间的关系

    当代理类和目标类实现了同一个接口,为兄弟关系时,proxyTargetClass=false,采用jdk

    当代理类继承了目标类的时候,为父子关系时,proxyTargetClass=true,采用cglib

    在Spring中,不光是@AOP注解,@Transtation注解也采取了同样的方式进行代理,大家可以自己去查看TransactionAutoConfiguration源码的这个类,也采用了同样的方法实现的动态代理

    展开全文
  • Jdk代理和CGLIB代理的区别

    千次阅读 2020-12-09 12:42:34
    java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。核心是实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。 而cglib动态代理是...

    1.原理区别

    java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。核心是实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。

    而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。核心是实现MethodInterceptor接口,使用intercept()方法进行面向切面的处理,调用相应的通知。

    1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

    2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP

    3. 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

    可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>
    springboot项目配置: spring.aop.proxy-target-class=false

    2.CGlib比JDK快?

    1、CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

    2、在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理。

    3、在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。

    3.各自局限:

    1、JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理。

    2、cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

    4. 总结

    在这里插入图片描述

    展开全文
  • 附件为java 动态代理实例,有全码,包括测试代码。 代码少,注释全。 对理解代理非常不错。
  • 笔者用注解方式实现SpringAOP时,发生了一件怪异的事情。...为false就是和原对象不是一个类型 instanceof 判断为false,通过jdk代理,基于接口实现。 对于编程,哪有什么怪异的事情,只是你对底层不甚了解罢了。
  • 在动态代理学习(二)JDK动态代理源码分析中我已经讲JDK底层生成的字节码文件反编译成了java代码,如下: public final class proxy extends Proxy implements MyService { private static Method m1; private ...
  • jdk动态代理使用详解

    万次阅读 多人点赞 2022-06-18 20:07:13
    jdk动态代理和cglib静态代理使用详解
  • Java JDK代理、CGLIB、AspectJ代理分析比较
  • SpringBoot中修改proxyTargetClass,但事务代理始终为CGLIB 关于@transactional使用在接口上的问题 Spring事务注解@Transactional的坑爹陷阱 关于Spring事务注解@Transactional一个疑问,求大神帮忙指点 另外: ...
  • 设计模式-代理模式(jdk代理和cglib代理详解)

    千次阅读 多人点赞 2017-06-22 11:24:42
    说起代理模式,详细很多人早已经很理解,但对于我这个菜鸟,理解的可能还是不到位,写一次博客加深印象。 什么是代理模式呢?代理模式是常用的Java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责...
  • 为什么JDK代理不像CGLib代理一样继承目标类反而去实现其接口呢? 因为JDK代理生成的代理类,默认会继承Proxy 类,由于java是单继承,所以不能继承目标类只能实现其接口 1.首先把JDK动态代理生成的类: 继承了Proxy类...
  • 面试中会遇见面试官:JDK代理与Spring cglib代理的区别:  简单的回答:  1,JDK只能代理接口,cglib代理的是类。  2,JDK射机制生成一个实现代理接口的匿名类,cglib是生成一个子类,覆盖其中的方法。 ...
  • 使用ImportBeanDefinitionRegistrar、JDK代理、FactoryBean模拟mybatis原理
  • JDK动态代理

    2022-02-05 09:59:03
    动态代理(理解) 这笔记能让你把动态代理掌握到什么程度呢? 1.什么是动态代理? 2.动态代理能做什么? 3.mybatis spring 框架中提到动态代理 你不会懵逼; 第一章:代理的介绍 1.什么是代理 代理 无处不在; 中介,...
  • 本文是根据《深入分析Java Web技术内幕》一书第十三章探讨 ...JDK的动态代理,就是在程序运行的过程中,根据被代理的接口来动态生成代理类的class文件,并加载运行的过程。代理的目的是调用目标方法时可
  • JDK代理和CGLIB代理的区别 区别 JDK: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。 CGKIB: cglib动态代理是利用asm开源包,对代理对象类的class文件加载...
  • 这篇文章不对JDK代理和CGLIB代理的内部实现细节讲解,这只是简单提一下如何使用,以及代理技术在实际中的用处。 先说一下静态代理。 明确一个原则,写出的代码投入到生产中后,最好不要对代码再进行修改。 比如...
  • 切面编程是Spring中非常重要的一个模块,切面编程的实现原理是动态代理,那么动态代理又有两种实现方式:一种方法是直接实现JDK中的InvocationHandler接口,另一种方法是继承CGLIB。 首先如果不是很清楚两者的区别...
  • 代理模式 什么是代理模式 代理模式是设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式。他在对象B的基础上提供了一层访问控制,当你需要访问对象B时,你需要经过对象B的代理对象A来...
  • JDK代理和Cglib代理

    2013-11-20 14:54:55
    JDK代理和Cglib代理,下载源码清楚了解二者区别
  • 第一种是JDK提供的基于接口的动态代理,要求被代理的类必须至少实现一个接口。 2. 第二种是第三方cglib提供的基于子类的动态代理,。至少要继承一个类。 我们这里 来讲解,动态代理,以及第一种实现动态代理的方式 ...
  • java-动态代理-jdk代理、cglib代理、生成字节码文件. 一、JDK动态代理和CGLIB字节码生成的区别?  * JDK动态代理只能对实现了接口的类生成代理,而不能针对类  * CGLIB是针对类实现代理,主要是对指定的类...
  • JDK动态代理原理解析

    千次阅读 2022-03-14 16:51:39
    1、回顾一下JDK动态代理的核心参数 如果我们要为target类创建一个【JDK动态代理对象】,那么我们必须要传入如下三个核心参数 加载target类的类加载器 target类实现的接口 InvocationHandler 为什么必须要这三个...
  • 编写服务类和接口,这个是真正的服务提供者,在JDK代理接口是必须的。 .编写代理类,提供绑定和代理方法。 JDK动态代理最大的缺点就是需要提供接口直接看例子:接口类:HelloService:p...
  • JDK动态代理和CGLIB动态代理

    千次阅读 2022-05-22 21:05:07
    动态代理中用的比较多的两种:JDK动态代理、CGLIB动态代理JDK动态代理 使用JDK的java.lang.reflect.Proxy类的newProxyInstance方法实现的代理。 用一个测试接口看下具体实现: public interface ...
  • jdk代理和cglib代理区别和例子

    千次阅读 2018-09-06 16:09:54
    代理目标 给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问,这句话的重点在于控制。 如何实现 既然要控制那么如何实现呢?在方法执行之前、之后加上自己的逻辑处理就可以了。比如权限检查:...
  • 一文带你了解JDK动态代理的原理
  • Jdk动态代理 底层

    2021-01-20 03:10:25
    java动态代理主要有2种,Jdk动态代理、Cglib动态代理,本文主要讲解Jdk动态代理的使用、运行机制、以及源码分析。当spring没有手动开启Cglib动态代理,即:或@EnableAspectJAutoProxy(proxyTargetClass = true),...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 181,035
精华内容 72,414
关键字:

jdk代理

友情链接: MSP430 OLED IIC.rar