在SpringAOP中应用了动态代理DynamicProxy
- 格式:ppt
- 大小:1.29 MB
- 文档页数:34
彻底讲透SpringAOP动态代理,原理源码深度剖析!1、AOP:【动态代理】定义指在程序运⾏期间动态的将某段代码切⼊到指定⽅法指定位置进⾏运⾏的编程⽅式;2、基于注解aop的开发流程1、导⼊aop模块;Spring AOP:(spring-aspects)2、定义⼀个业务逻辑类(MathCalculator);在业务逻辑运⾏的时候将⽇志进⾏打印(⽅法之前、⽅法运⾏结束、⽅法出现异常,xxx)3、定义⼀个⽇志切⾯类(LogAspects):切⾯类⾥⾯的⽅法需要动态感知MathCalculator.div运⾏到哪⾥然后执⾏;通知⽅法:前置通知(@Before):logStart:在⽬标⽅法(div)运⾏之前运⾏后置通知(@After):logEnd:在⽬标⽅法(div)运⾏结束之后运⾏(⽆论⽅法正常结束还是异常结束)返回通知(@AfterReturning):logReturn:在⽬标⽅法(div)正常返回之后运⾏异常通知(@AfterThrowing):logException:在⽬标⽅法(div)出现异常以后运⾏环绕通知(@Around):动态代理,⼿动推进⽬标⽅法运⾏(joinPoint.procced())给切⾯类的⽬标⽅法标注何时何地运⾏(通知注解);将切⾯类和业务逻辑类(⽬标⽅法所在类)都加⼊到容器中;必须告诉Spring哪个类是切⾯类(给切⾯类上加⼀个注解:@Aspect)给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】在Spring中很多的 @EnableXXX;总结:三步:1)、将业务逻辑组件和切⾯类都加⼊到容器中;告诉Spring哪个是切⾯类(@Aspect)2)、在切⾯类上的每⼀个通知⽅法上标注通知注解,告诉Spring何时何地运⾏(切⼊点表达式)3)、开启基于注解的aop模式;@EnableAspectJAutoProxy3、AOP原理:【看给容器中注册了什么组件,这个组件什么时候⼯作,这个组件的功能是什么?】注解aop开发,我们在配置类中加⼊了@EnableAspectJAutoProxy这个注解我们来看⼀下@EnableAspectJAutoProxy是什么?@Import(AspectJAutoProxyRegistrar.class):给容器中导⼊AspectJAutoProxyRegistrar利⽤AspectJAutoProxyRegistrar⾃定义给容器中注册bean;BeanDefinetioninternalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator给容器中注册⼀个AnnotationAwareAspectJAutoProxyCreator;所以这个注解式给容器中注⼊了AnnotationAwareAspectJAutoProxyCreator这样⼀个注解切⾯⾃动代理创建对象通过类的层级分析 AnnotationAwareAspectJAutoProxyCreator:AnnotationAwareAspectJAutoProxyCreator->AspectJAwareAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAutoProxyCreatorimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware,下⾯是AnnotationAwareAspectJAutoProxyCreator类的继承关系图:我们可以清楚的看到其实它是属于InstantiationAwareBeanPostProcessor 类型的后置处理器和BeanFactoryAware;我在之前分析过IOC源码的记载过程,知道InstantiationAwareBeanPostProcessor 会在bean的初始化之前,普通后置处理器执⾏之前创建代理对象。
SpringAOP⽰例与实现原理总结——传统springaop、基于切⾯注⼊、基于@Asp。
⼀、代码实践1)经典的Spring Aop经典的spring aop,是基于动态代理技术的。
实现⽅式上,最常⽤的是实现MethodInterceptor接⼝来提供环绕通知,创建若⼲代理,然后使⽤ProxyBeanFactory配置⼯⼚bean,⽣成拦截器链,完成拦截。
⽰例如下:1package demo.spring;23import org.aopalliance.intercept.MethodInterceptor;4import org.aopalliance.intercept.MethodInvocation;5import org.junit.Test;6import org.junit.runner.RunWith;7import org.springframework.beans.factory.annotation.Autowired;8import org.springframework.test.context.ContextConfiguration;9import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;1011 @RunWith(SpringJUnit4ClassRunner.class)12 @ContextConfiguration("classpath:spring-config.xml")13public class TraditionalSpringAopDemo {14 @Autowired15private Service proxy;1617 @Test18public void test() {19 proxy.execute("hello world!");20 }21 }2223interface Service {24void execute(String str);25 }2627class ServiceImpl implements Service {28 @Override29public void execute(String str) {30 System.out.println("execute invoke: " + str);31 }32 }3334class Interceptor1 implements MethodInterceptor {35 @Override36public Object invoke(MethodInvocation methodInvocation) throws Throwable {37 System.out.println("interceptor1,before invoke");38 Object ret = methodInvocation.proceed();39 System.out.println("interceptor1,after invoke");40return ret;41 }42 }4344class Interceptor2 implements MethodInterceptor {45 @Override46public Object invoke(MethodInvocation methodInvocation) throws Throwable {47 System.out.println("interceptor2,before invoke");48 Object ret = methodInvocation.proceed();49 System.out.println("interceptor2,after invoke");50return ret;51 }52 }xml⽂件配置:1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="/schema/beans"3 xmlns:xsi="/2001/XMLSchema-instance"4 xmlns:context="/schema/context"5 xmlns:aop="/schema/aop"6 xsi:schemaLocation="/schema/beans /schema/beans/spring-beans.xsd /schema/context /schema/context/sprin 78<context:component-scan base-package="demo.spring"/>910<bean class="demo.spring.ServiceImpl" id="service"></bean>11<bean class="demo.spring.Interceptor1" id="interceptor1"></bean>12<bean class="demo.spring.Interceptor2" id="interceptor2"></bean>13<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="proxy">14<property name="target" ref="service"/>15<property name="interceptorNames">16<list>17<value>interceptor1</value>18<value>interceptor2</value>19</list>20</property>21</bean>22</beans>结果:interceptor1,before invokeinterceptor2,before invokeexecute invoke: hello world!interceptor2,after invokeinterceptor1,after invoke可以看到拦截链的执⾏过程与拦截器顺序的关系。
java中代理,静态代理,动态代理以及springaop代理⽅式,实现原理统⼀汇总若代理类在程序运⾏前就已经存在,那么这种代理⽅式被成为静态代理,这种情况下的代理类通常都是我们在Java代码中定义的。
通常情况下,静态代理中的代理类和委托类会实现同⼀接⼝或是派⽣⾃相同的⽗类。
⼀、概述1. 什么是代理我们⼤家都知道微商代理,简单地说就是代替⼚家卖商品,⼚家“委托”代理为其销售商品。
关于微商代理,⾸先我们从他们那⾥买东西时通常不知道背后的⼚家究竟是谁,也就是说,“委托者”对我们来说是不可见的;其次,微商代理主要以朋友圈的⼈为⽬标客户,这就相当于为⼚家做了⼀次对客户群体的“过滤”。
我们把微商代理和⼚家进⼀步抽象,前者可抽象为代理类,后者可抽象为委托类(被代理类)。
通过使⽤代理,通常有两个优点,并且能够分别与我们提到的微商代理的两个特点对应起来:优点⼀:可以隐藏委托类的实现;优点⼆:可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做⼀些额外的处理。
2. 静态代理若代理类在程序运⾏前就已经存在,那么这种代理⽅式被成为静态代理,这种情况下的代理类通常都是我们在Java代码中定义的。
通常情况下,静态代理中的代理类和委托类会实现同⼀接⼝或是派⽣⾃相同的⽗类。
下⾯我们⽤Vendor类代表⽣产⼚家,BusinessAgent类代表微商代理,来介绍下静态代理的简单实现,委托类和代理类都实现了Sell接⼝,Sell接⼝的定义如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15public interface Sell { void sell(); void ad();}Vendor类的定义如下:public class Vendor implements Sell { public void sell() { System.out.println("In sell method");} public void ad() {System,out.println("ad method")}}从BusinessAgent类的定义我们可以了解到,静态代理可以通过聚合来实现,让代理类持有⼀个委托类的引⽤即可。
动态代理在Spring中的应⽤Spring中主要使⽤cglib和jdk动态代理,主要在SpringAop中有⼤量应⽤。
JDK动态代理jdk动态代理主要使⽤场景是被代理的对象有实现的接⼝。
最终⽣成的代理类:class $Proxy0 extends Proxy implements IDaojdk动态代理主要是基于反射,其实我们完全可以⾃⼰模拟;其中两个⽐较关键的思路:1. 使⽤反射解析⽬标对象的属性、⽅法等2. 根据解析的内容⽣成proxy.class,说⽩了就是把要⽣成的class按照字符串的形式拼接,最终通过ClassLoader加载。
package com.tian.proxy;import com.sun.jndi.toolkit.url.UrlUtil;import javax.tools.JavaCompiler;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;import java.io.*;import ng.reflect.Constructor;import ng.reflect.Method;import .URL;import .URLClassLoader;public class ProxyUtil {public static Object newInstance(Object target){Object proxy=null;Class targetInf = target.getClass().getInterfaces()[0];Method methods[] =targetInf.getDeclaredMethods();String line="\n";String tab ="\t";String infName = targetInf.getSimpleName();String content ="";String packageContent = "package com.tian;"+line;String importContent = "import "+targetInf.getName()+";"+line;String clazzFirstLineContent = "public class $Proxy implements "+infName+"{"+line;String filedContent =tab+"private "+infName+" target;"+line;String constructorContent =tab+"public $Proxy ("+infName+" target){" +line+tab+tab+"this.target =target;"+line+tab+"}"+line;String methodContent = "";for (Method method : methods) {String returnTypeName = method.getReturnType().getSimpleName();String methodName =method.getName();// Sting.class String.classClass args[] = method.getParameterTypes();String argsContent = "";String paramsContent="";int flag =0;for (Class arg : args) {String temp = arg.getSimpleName();//String//String p0,Sting p1,argsContent+=temp+" p"+flag+",";paramsContent+="p"+flag+",";flag++;}if (argsContent.length()>0){argsContent=argsContent.substring(0,stIndexOf(",")-1);paramsContent=paramsContent.substring(0,stIndexOf(",")-1);}methodContent+=tab+"public "+returnTypeName+" "+methodName+"("+argsContent+") {"+line+tab+tab+"System.out.println(\"log\");"+line+tab+tab+"target."+methodName+"("+paramsContent+");"+line+tab+"}"+line;}content=packageContent+importContent+clazzFirstLineContent+filedContent+constructorContent+methodContent+"}";File file =new File("d:\\com\\tian\\$Proxy.java");try {if (!file.exists()) {file.createNewFile();}FileWriter fw = new FileWriter(file);fw.write(content);fw.flush();fw.close();JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);Iterable units = fileMgr.getJavaFileObjects(file);pilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);t.call();fileMgr.close();URL[] urls = new URL[]{new URL("file:D:\\\\")};URLClassLoader urlClassLoader = new URLClassLoader(urls);Class clazz = urlClassLoader.loadClass("com.tian.$Proxy");Constructor constructor = clazz.getConstructor(targetInf);proxy = constructor.newInstance(target);}catch (Exception e){e.printStackTrace();}return proxy;}}IDao proxy = (IDao) ProxyUtil.newInstance(newCGLIB动态代理cglib代理主要使⽤场景是:被代理对象的是类⽽没有任何接⼝实现。
浅析Spring 中AOP 的实现原理——动态代理⼀、前⾔ 最近在复习的相关内容,刚刚⼤致研究了⼀下中,的实现原理。
这篇博客就来简单地聊⼀聊的是如何实现的,并通过⼀个简单的测试⽤例来验证⼀下。
废话不多说,直接开始。
⼆、正⽂2.1 Spring AOP 的实现原理 的实现原理其实很简单,就是通过动态代理实现的。
如果我们为的某个配置了切⾯,那么在创建这个的时候,实际上创建的是这个的⼀个代理对象,我们后续对中⽅法的调⽤,实际上调⽤的是代理类重写的代理⽅法。
⽽的使⽤了两种动态代理,分别是JDK 的动态代理,以及CGLib 的动态代理。
(⼀)JDK 动态代理 Spring 默认使⽤JDK 的动态代理实现AOP ,类如果实现了接⼝,Spring 就会使⽤这种⽅式实现动态代理。
熟悉语⾔的应该会对动态代理有所了解。
实现动态代理需要两个组件,⾸先第⼀个就是接⼝。
我们在使⽤的动态代理时,需要编写⼀个类,去实现这个接⼝,然后重写⽅法,这个⽅法其实就是我们提供的代理⽅法。
然后动态代理需要使⽤的第⼆个组件就是这个类,我们可以通过这个类的⽅法,返回⼀个代理对象。
⽣成的代理类实现了原来那个类的所有接⼝,并对接⼝的⽅法进⾏了代理,我们通过代理对象调⽤这些⽅法时,底层将通过反射,调⽤我们实现的⽅法。
(⼆)CGLib 动态代理 的动态代理存在限制,那就是被代理的类必须是⼀个实现了接⼝的类,代理类需要实现相同的接⼝,代理接⼝中声明的⽅法。
若需要代理的类没有实现接⼝,此时的动态代理将没有办法使⽤,于是会使⽤的动态代理来⽣成代理对象。
直接操作字节码,⽣成类的⼦类,重写类的⽅法完成代理。
以上就是实现动态的两种⽅式,下⾯我们具体来谈⼀谈这两种⽣成动态代理的⽅式。
2.2 JDK 的动态代理(⼀)实现原理 的动态代理是基于反射实现。
通过反射,⽣成⼀个代理类,这个代理类实现了原来那个类的全部接⼝,并对接⼝中定义的所有⽅法进⾏了代理。
当我们通过代理对象执⾏原来那个类的⽅法时,代理类底层会通过反射机制,回调我们实现的接⼝的⽅法。
软件架构设计模式随着面向对象技术的发展和广泛应用,设计模式不再是一个新兴的名词,它已逐步成为系统架构人员、设计人员、分析人员以及程序开发人员所需掌握的基本技能之一。
设计模式已广泛应用于面向对象的设计和开发,成为面向对象领域的一个重要组成部分。
设计模式通常可分为三类:创建型模式、结构型模式和行为型模式。
1.创建型模式概述创建型模式(CreationalPattern)对类的实例化过程及对象的创建过程进行了抽象,能够使软件模块做到与对象的创建和组织无关。
创建型模式隐藏了对象的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
在掌握创建型模式时,需要回答以下三个问题:创建什么(What)、由谁创建(Who)和何时创建(When)。
创建型模式主要包括简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式。
以下介绍其中使用频率较高的几种模式,包括简单工厂模式、工厂方法模式、抽象工厂模式、单例模式。
1.1简单工厂模式简单工厂模式(SimpleFatoryPattern),又称静态工厂方法模式(StaticFactotyMethodPattern),属于类创建型模式。
在简单工厂模式中,定义一个类,可以根据参数的不同返回不同的类的实例,这些类具有公共的父类和一些公共的方法。
简单工厂模式不属于GoF设计模式,它是最简单的工厂模式。
简单工厂模式专门定义一个类来负责创建其他类的实例,这个类称为工厂类,被创建的实例通常都具有共同的父类。
在简单工厂模式中,工厂类包含必要的判断逻辑,决定在什么时候创建哪一个产品类实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品,简单工厂模式通过这种方式实现了对责任的划分。
但是由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响;同时系统扩展较为困难,一旦添加新产品就不得不修改工厂逻辑,违反了开闭原则,并造成工厂逻辑过于复杂。
动态代理Java动态代理类位于ng.reflect包下,一般主要涉及到以下两个类:(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。
在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args 为该方法的参数数组。
这个抽象方法在代理类中动态实现。
(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。
你当然可以把该class的实例当作这些interface中的任何一个来用。
当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
在使用动态代理类时,我们必须实现InvocationHandler接口,以第一节中的示例为例:抽象角色(之前是抽象类,此处应改为接口):public interface Subject{abstract public void request();}具体角色RealSubject:同上;代理角色:import ng.reflect.Method;import ng.reflect.InvocationHandler;public class DynamicSubject implements InvocationHandler {private Object sub;public DynamicSubject() {}public DynamicSubject(Object obj) {sub = obj;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before calling " + method);method.invoke(sub,args);System.out.println("after calling " + method);return null;}}该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;此外,在该类还实现了invoke方法,该方法中的method.invoke(sub,args);其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,args为执行被代理对象相应操作所需的参数。
Java的动态代理(dynamic proxy)PS;本文档由北大青鸟广安门收集自互联网,仅作分享之用。
动态代理(以下称代理),利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象)(Using Java Reflection to create dynamic implementations of interfaces at runtime)。
代理的是接口(Interfaces),不是类(Class),更不是抽象类。
动态代理有什么用解决特定问题:一个接口的实现在编译时无法知道,需要在运行时才能实现实现某些设计模式:适配器(Adapter)或修饰器(Decorator)面向切面编程:如AOP in Spring创建动态代理利用Java的Proxy类,调用Proxy.newProxyInstance(),创建动态对象十分简单。
InvocationHandler handler = new MyInvocationHandler(...);Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });Foo f = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });//或更简单Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class },handler);Proxy.newProxyInstance()方法有三个参数:1. 类加载器(Class Loader)2. 需要实现的接口数组3. InvocationHandler接口。
AOP从静态代理到动态代理(Emit实现)详解【前⾔】AOP(Aspect Orient Programming),我们⼀般称为⾯向⽅⾯(切⾯)编程,作为⾯向对象的⼀种补充,⽤于处理系统中分布于各个模块的横切关注点,⽐如事务管理、⽇志、缓存等等。
AOP实现的关键在于AOP框架⾃动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;⽽动态代理则以Spring AOP为代表。
何为切⾯?⼀个和业务没有任何耦合相关的代码段,诸如:调⽤⽇志,发送邮件,甚⾄路由分发。
⼀切能为代码所有且能和代码充分解耦的代码都可以作为⼀个业务代码的切⾯。
我们为什么要AOP?那我们从⼀个场景举例说起:如果想要采集⽤户操作⾏为,我们需要掌握⽤户调⽤的每⼀个接⼝的信息。
这时候的我们要怎么做?如果不采⽤AOP技术,也是最简单的,所有⽅法体第⼀句话先调⽤⼀个⽇志接⼝将⽅法信息传递记录。
有何问题?实现业务没有任何问题,但是随之⽽来的是代码臃肿不堪,难以调整维护的诸多问题(可⾃⾏脑补)。
如果我们采⽤了AOP技术,我们就可以在系统启动的地⽅将所有将要采集⽇志的类注⼊,每⼀次调⽤⽅法前,AOP框架会⾃动调⽤我们的⽇志代码。
是不是省去了很多重复⽆⽤的劳动?代码也将变得⾮常好维护(有朝⼀⽇不需要了,只需将切⾯代码注释掉即可)接下来我们看看AOP框架的⼯作原理以及实过程。
【实现思路】AOP框架呢,⼀般通过静态代理和动态代理两种实现⽅式。
何为静态代理?静态代理,⼜叫编译时代理,就是在编译的时候,已经存在代理类,运⾏时直接调⽤的⽅式。
说的通俗⼀点,就是⾃⼰⼿动写代码实现代理类的⽅式。
我们通过⼀个例⼦来展现⼀下静态代理的实现过程:我们这⾥有⼀个业务类,⾥⾯有⽅法Test(),我们要在Test调⽤前和调⽤后分别输出⽇志。
我们既然要将Log当作⼀个切⾯,我们肯定不能去动原有的业务代码,那样也违反了⾯向对象设计之开闭原则。
那么我们要怎么做呢?我们定义⼀个新类 BusinessProxy 去包装⼀下这个类。
SpringAop动态代理(proxy)两种实现⽅式JDK和CGlib前⾔:学习过spring的都知道,IOC和AOP是spring⾥最基础的两个核⼼技术。
在学习AOP(⾯向切⾯编程)的时候⽤到了动态代理,因为AOP的底层实现原理使⽤的就是动态代理。
spring默认使⽤的是jdk提供的动态代理,其实是两种都⽀持。
⽬录⽬录)什么是动态代理?在了解动态代理之前,我现在简单介绍下什么代理。
代理:按照字⾯意思,就是代替你去做⼀些事情。
代替你去完成⼀些功能,或者做⼀些本来应该你来做的事情。
这是字⾯意思理解,在⾯向对象的程序设计语⾔⾥:动态代理是在你原有的功能基础之上,对功能进⾏增强的⼀种实现⼿段。
通过动态代理,并且符合开闭原则的前提增强⽅法的功能。
这也是AOP的思想,通过不修改原有代码,把你的代码织⼊到指定的⽅法中。
代理模式:代理模式(Proxy):为其他对象提供⼀个代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,⽐如说:要访问的对象在远程的机器上。
在⾯向对象系统中,有些对象由于某些原因(⽐如对象创建开销很⼤,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使⽤者或者系统结构带来很多⿇烦,我们可以在访问此对象时加上⼀个对此对象的访问层。
代理模式的元素是:共同接⼝、代理对象、⽬标对象。
代理模式的⾏为:由代理对象执⾏⽬标对象的⽅法、由代理对象扩展⽬标对象的⽅法。
代理模式的宏观特性:对客户端只暴露出接⼝,不暴露它以下的架构。
JDKProxDynameic 和 CGlibProxDynameic区别jdk的动态代理是代理的接⼝,并且只能代理有接⼝的类。
如果这个类没有实现任何接⼝,jdk的动态代理是⽆法代理的。
这个时候就可以使⽤cglib去对类的字节码进⾏底层的继承代理,通过继承被代理对象。
也就是JDKProxDynameic 代理的接⼝CGlibProxDynameic代理的类(如果类被final修饰就不能被代理成功)两种动态代理实现⽅式:JDKProxDynameic(jdk提供)jdk的动态代理主要是:InvocationHandler接⼝和proxy类import ng.reflect.InvocationHandler; 接⼝InvocationHandler这个接⼝⾥主要是使⽤invoke⽅法,增强被代理对象的⽅法。