在SpringAOP中应用了动态代理DynamicProxy
彻底讲透SpringAOP动态代理,原理源码深度剖析!

彻底讲透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。。。

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中代理,静态代理,动态代理以及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中的应⽤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的实现原理——动态代理

浅析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设计模式,它是最简单的工厂模式。
简单工厂模式专门定义一个类来负责创建其他类的实例,这个类称为工厂类,被创建的实例通常都具有共同的父类。
在简单工厂模式中,工厂类包含必要的判断逻辑,决定在什么时候创建哪一个产品类实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品,简单工厂模式通过这种方式实现了对责任的划分。
但是由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响;同时系统扩展较为困难,一旦添加新产品就不得不修改工厂逻辑,违反了开闭原则,并造成工厂逻辑过于复杂。
动态代理(Dynamic Proxy)

动态代理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)

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接口。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
代理模式
模式动机
代理模式
模式动机
代理模式
模式动机
通过引入一个新的对象(如小图片和远程代理 对象)来实现对真实对象的操作或者将新的对 象作为真实对象的一个替身,这种实现机制即 为代理模式,通过引入代理对象来间接访问一 个对象,这就是代理模式的模式动机。
代理模式
模式定义
代理模式(Proxy Pattern) :给某一个对象提供一个代 理,并由代理对象控制对原对象的引用。代理模式的英 文叫做Proxy或Surrogate,它是一种对象结构型模式。
代理模式
代理模式实例与解析
实例二:数学运算代理
Calculator + + + + add (double x, double y) sub (double x, double y) mul (double x, double y) div (double x, double y) ... : double : double : double : double
RealPermission
permission
+ + + + +
modifyUserInfo () viewNote () publishNote () modifyNote () setLevel (int level) ...
: void : void : void : void : void
代理模式
代理模式实例与解析
实例一:论坛权限控制代理
• 在一个论坛中已注册用户和游客的权限不同,已注册的用 户拥有发帖、修改自己的注册信息、修改自己的帖子等功 能;而游客只能看到别人发的帖子,没有其他权限。使用 代理模式来设计该权限管理模块。 • 在本实例中我们使用代理模式中的保护代理,该代理用于 控制对一个对象的访问,可以给不同的用户提供不同级别 的使用权限。
real=new RealCalculator();
ProxyCalculator - real : RealCalculator + init () + add (double x, double y) + sub (double x, double y) + mul (double x, double y) + div (double x, double y) ...
Client
PermissionProxy - permission : RealPermission = new RealPermission() - level : int =0 + modifyUserInfo () : void + viewNote () : void + publishNote () : void + modifyNote () : void + setLevel (int level) : void
代理模式
代理模式实例与解析
实例一:论坛权限控制代理
• 参考代码 (Chapter 16 Proxy\sample01)
演示……
代理模式
代理模式实例与解析
实例二:数学运算代理 • 模拟应用远程代理来访问另外一个应用程序域中的对 象,如果在远程实现了加减乘除等运算,在本地需要 调用,那么可以考虑在本地设置一个代理。
real.add(x,y);
RealCalculator : void : double : double : double : double
代理模式
模式定义
Proxy Pattern: Provide a surrogate or placeholder for another object to control access to it. Frequency of use: medium high
代理模式
Subject
RealSuபைடு நூலகம்ject
realSubject
+ request () ...
代理模式
模式结构
代理模式包含如下角色: • Subject: 抽象主题角色 • Proxy: 代理主题角色 • RealSubject: 真实主题角色
代理模式
模式分析
代理模式示意结构图比较简单,一般可以简化为如下图所示, 但是在现实中要复杂很多。
代理模式
代理模式实例与解析
实例一:论坛权限控制代理
AbstractPermission + + + + + modifyUserInfo () viewNote () publishNote () modifyNote () setLevel (int level) : void : void : void : void : void
接口 实现 实现
代理类
调用
实现类
代理模式
模式分析
典型的代理类实现代码:
public class Proxy implements Subject { private RealSubject realSubject = new RealSubject(); public void preRequest() {…...} public void request() { preRequest(); realSubject.request(); postRequest(); } public void postRequest() {……} }
代理模式
本章教学内容
代理模式
模式动机与定义 模式结构与分析 模式实例与解析 模式效果与应用
模式扩展
代理模式
模式动机
在某些情况下,一个客户不想或者不能直接引用一个对 象,此时可以通过一个称之为“代理”的第三者来实现 间接引用。代理对象可以在客户端和目标对象之间起到 中介的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务。
模式结构
+ request () ...
Client
Proxy - realSubject : RealSubject + preRequest () + request () + postRequest () ...
preRequest(); realSubject.request(); postRequest();