在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接口。
AOP从静态代理到动态代理(Emit实现)详解
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
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⽅法,增强被代理对象的⽅法。
Proxy模式在Spring AOP中的使用
Proxy模式在Spring AOP中的使用Spring是一种流行的开源Java应用程序开发框架,在许多企业级应用程序中广泛使用。
它提供了许多功能和工具,以帮助开发者构建高质量、高可用、易于维护的应用程序。
其中,Spring AOP是Spring框架中最受欢迎的模块之一。
它是基于Java的AOP 框架,可以为程序员提供方便的技术来解决复杂的问题。
其中利用到了Proxy模式,本文就来探究一下Proxy模式在Spring AOP 中的使用。
1. 什么是Proxy模式?Proxy模式是一种常用的设计模式,它是一种结构型模式,它可以为其他对象提供一种代理以控制对这个对象的访问。
Proxy模式中,代理对象和真实对象实现了相同的接口,代理对象将所有的请求转发给真实对象,同时还可以在转发请求前或之后执行一些额外的操作,这使得代理对象可以自行决定是否或者何时向真实对象转发请求,并具有更多的灵活性和扩展性。
2. 为什么使用Proxy模式?Proxy模式的主要优点是,它可以为其他对象提供一种代理以控制对这个对象的访问,从而可以提供更多的控制和灵活性。
它可以在不修改既有代码的情况下,扩展或修改对象的行为,这使得代理对象可以自行决定是否或者何时向真实对象转发请求,并具有更多的灵活性和扩展性。
此外,Proxy模式还可以通过减少对象的创建和销毁次数,从而提高程序的性能。
3. 如何在Spring AOP中使用Proxy模式?Spring框架中的AOP模块利用了Proxy模式来提供AOP功能。
它使用了两种类型的代理:JDK动态代理和CGLIB动态代理。
其中,JDK动态代理只能代理实现了接口的类,而CGLIB动态代理可以代理没有实现接口的类。
Spring默认使用的是JDK动态代理。
在Spring AOP中使用Proxy模式的一般步骤如下:(1) 定义一个切面切面是一个类,用于定义切点和切面的行为。
切点定义了程序中需要拦截的特定方法,切面定义了在拦截这些方法时要执行的通知。
aop动态代理的实现原理
AOP(面向切面编程)是一种通过预编译方式和运行期间动态代理实现程序功能的统一维护的技术。
在AOP中,动态代理是一种常见的实现方式。
动态代理的实现原理主要是通过使用动态代理类来代理目标方法,在调用目标方法之前和之后执行一些额外的代码。
这个过程可以通过以下步骤完成:
1.创建代理对象:首先需要创建一个代理对象,这个对象通常是一个实现了
InvocationHandler接口的类实例。
2.实现invoke方法:在InvocationHandler接口中,有一个invoke方法需要实现。
这个方法会在调用目标方法之前被调用,可以用来执行一些额外的代码,例如日志记录、权限验证等。
3.调用目标方法:在invoke方法中,需要调用目标方法。
可以通过反射机制来获取
目标对象的实例和方法信息,并调用目标方法。
4.返回结果:目标方法执行完成后,需要将结果返回给调用者。
可以在invoke方法
中返回目标方法的执行结果,或者根据需要修改结果。
在AOP中,动态代理可以用来实现切面(Aspect),将业务逻辑的各个部分进行
隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
springboot中springaop实现的动态代理-cglib和JDK
自动配置,默认是true 但是有一情况况例外:
存在@EnableAsync和@EnableCaching,默认 spring.aop.proxy-target-class属性值为false
示例代码:
testService存在@Async注解,这样spring.aop.proxy-target-class属性值为false和ITestService为接口类,则使用JDK动态注解
博客园 用户登录 代码改变世界 密码登录 短信登录 忘记登录用户名 忘记密码 记住我 登录 第三方登录/注册 没有账户, 立即注册
springboot中 springaop实现的动态代理 -cglib和 JDK
spring aop默认使用JDK还是Cglib动态代理? 一般情况:实现接口类,接口类为JDK ,实现类为Cglib动态代理 springboot2.x默认使用的代理是cglib代理 实现原理:
spring基础概念AOP与动态代理理解
spring基础概念AOP与动态代理理解⼀、代理模式代理模式的英⽂叫做Proxy或Surrogate,中⽂都可译为”代理“,所谓代理,就是⼀个⼈或者⼀个机构代表另⼀个⼈或者另⼀个机构采取⾏动。
在⼀些情况下,⼀个客户不想或者不能够直接引⽤⼀个对象,⽽代理对象可以在客户端和⽬标对象之间起到中介的作⽤。
以简单模拟事务的执⾏过程说明各种代理区别1.1 静态代理由程序员创建或由特定⼯具⾃动⽣成源代码,再对其编译。
在程序运⾏前,代理类的.class⽂件就已经存在了。
public interface PersonDao {void savePerson();}public class PersonDaoImpl implements PersonDao {@Overridepublic void savePerson() {System.out.println("save person");}}public class Transaction {void beginTransaction(){System.out.println("begin Transaction");}void commit(){System.out.println("commit");}}接下来编写静态代理类---实现PersonDao接⼝/*** 静态代理类* @author qjc*/public class PersonDaoProxy implements PersonDao{PersonDao personDao;Transaction transaction;public PersonDaoProxy(PersonDao personDao, Transaction transaction) {this.personDao = personDao;this.transaction = transaction;}@Overridepublic void savePerson() {this.transaction.beginTransaction();this.personDao.savePerson();mit();}}测试/*** 测试静态代理* @author qjc*/public class TestPersonProxy {@Testpublic void testSave(){PersonDao personDao = new PersonDaoImpl();Transaction transaction = new Transaction();PersonDaoProxy proxy = new PersonDaoProxy(personDao, transaction);proxy.savePerson();}}总结:1、静态代理模式并没有做到事务的重⽤2、假设dao有100个类,100个proxy,接⼝中有多少⽅法,在proxy层就得实现多少⽅法,有多少⽅法就要开启和提交多少事务3、如果⼀个proxy实现了多个接⼝,如果其中的⼀个接⼝发⽣变化(添加了⼀个⽅法),那么proxy也要做相应改变1.2 JDK动态代理动态代理类:在程序运⾏时,运⽤反射机制动态创建⽽成。
Spring中AOP概念与两种动态代理模式原理详解
Spring中AOP概念与两种动态代理模式原理详解⽬录1.概念1.AOP技术简介2.AOP的优势3.Spring AOP术语4.AOP 开发明确的事项2.AOP底层实现1.AOP 的动态代理技术:3.基于cglib的动态代理代码总结1.概念1.AOP技术简介AOP 为Aspect Oriented Programming 的缩写,意思为⾯向切⾯编程,是通过预编译⽅式和运⾏期动态代理实现程序功能的统⼀维护的⼀种技术。
AOP 是 OOP 的延续,是软件开发中的⼀个热点,也是Spring框架中的⼀个重要内容,是函数式编程的⼀种衍⽣范型。
利⽤AOP可以对业务逻辑的各个部分进⾏隔离,从⽽使得业务逻辑各部分之间的耦合度降低,提⾼程序的可重⽤性,同时提⾼了开发的效率。
2.AOP的优势作⽤:在程序运⾏期间,在不修改源码的情况下对⽅法进⾏功能增强优势:减少重复代码,提⾼开发效率,并且便于维护3.Spring AOP术语Spring 的 AOP 实现底层就是对上⾯的动态代理的代码进⾏了封装,封装后我们只需要对需要关注的部分进⾏代码编写,并通过配置的⽅式完成指定⽬标的⽅法增强。
在正式讲解 AOP 的操作之前,我们必须理解 AOP 的相关术语,常⽤的术语如下:Target(⽬标对象):代理的⽬标对象Proxy (代理):⼀个类被 AOP 织⼊增强后,就产⽣⼀个结果代理类Joinpoint(连接点):所谓连接点是指那些被拦截到的点。
在spring中,这些点指的是⽅法,因为spring只⽀持⽅法类型的连接点.(可能被增强的⽅法)Pointcut(切⼊点):所谓切⼊点是指我们要对哪些 Joinpoint 进⾏拦截的定义(被增强的⽅法)Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知(对⽬标对象增强的⽅法)Aspect(切⾯):是切⼊点和通知(引介)的结合(⽬标⽅法+增强=切⾯)Weaving(织⼊):是指把增强应⽤到⽬标对象来创建新的代理对象的过程。
【Spring】大白话聊聊代理模式——动态代理
【Spring】⼤⽩话聊聊代理模式——动态代理为什么要使⽤代理模式呢?打个⽐⽅,我虽然不会打篮球,但我很喜欢A锥,可是国内我⼜买不起,发现海淘的A锥,既经济⼜实惠(咱也不知道是不是真货,咱也不敢问),不过我发现我去访问海外电商极度费劲,此时我该怎么办?我突然想到了代购⽼黄,我们可以通过⽼黄啊,来帮我们获取到我们⼼仪的A锥。
从静态代理的⾓度我们分析⼀下⽼黄代理如何运作:所以对于⽼黄,也就代理来说,其实就是⼀个搬运⼯。
也⽐如我们的博客系统,我们查看⼀个⽂章,如果⽂章中有个特别⼤的图⽚需要加载,此时如果等在加载完图⽚再进⾏展⽰图⽚以后的⽂章内容,是⾮常耗时的操作,那么此时我们就可以使⽤Proxy来先代替那个图⽚。
我们先看看静态代理是如何实现上述鞋⼯⼚的:1》先创建⼀个鞋⼯⼚接⼝:public interface ShoeFactory {void saleShoe(int size);}2》创建⼀个AJ鞋⼚来实现这个接⼝:public class AJFactory implements ShoeFactory {@Overridepublic void saleShoe(int size) {System.out.println("根据您的需求,为您定制了⼀个size为:" + size + "的AJ");}}3》看看⽼黄是如何代理的:/*** 代理类*/public class LaohuangProxy implements ShoeFactory {private ShoeFactory factory;public LaohuangProxy(ShoeFactory factory) {super();this.factory = factory;}@Overridepublic void saleShoe(int size) {doSomethingBefore();//前置增强factory.saleShoe(size);doSomethingAfter();//后置增强}private void doSomethingAfter() {System.out.println("提供快递服务⼀条龙");}private void doSomethingBefore() {System.out.println("根据您的需求进⾏市场调研");}public static void main(String[] args) {AJFactory factory = new AJFactory();//1.有⼀个AJ鞋⼯⼚LaohuangProxy laohuangProxy = new LaohuangProxy(factory);//2.⽼黄代理laohuangProxy.saleShoe(43);//3.帮我订购⼀双43码鞋}}但此时,快过情⼈节了,这空⼿确实不太⾏啊,我准备给我的⼥神⼩娜个迪奥999⼝红(就是这么⼤⽓),但是专柜已经被抢空了,所以我⼜想到了⽆所不能的⽼黄,找他帮我代购⼀波:如果继续使⽤静态代理,我们需要再创建⼀个⼝红制造⼚接⼝和迪奥⼝红⼯⼚类,话不多说,撸码就完了:1》声明⼀个⼝红⼯⼚接⼝public interface LipstickFactory {void saleLipstick(String color);}2》创建⼀个迪奥⼯⼚类:public class DiorFactory implements LipstickFactory {@Overridepublic void saleLipstick(String color) {System.out.println("根据您的需求,为您包装了⼀个颜⾊为:" + color + "的迪奥⼝红");}}3》看看⽼黄代理的改动:public class LaohuangProxy implements ShoeFactory, LipstickFactory { //改动1:需要多继承⼀个接⼝private ShoeFactory factory;private LipstickFactory lipstickFactory;//改动2:由于代理类只是⼀个搬运⼯,所以需要多包含⼀个⼝红⼯⼚public LaohuangProxy(ShoeFactory factory) {super();this.factory = factory;}//改动3:需要实现⼀个新的构造函数public LaohuangProxy(LipstickFactory lipstickFactory) {super();this.lipstickFactory = lipstickFactory;}@Overridepublic void saleShoe(int size) {doSomethingBefore();//前置增强factory.saleShoe(size);doSomethingAfter();//后置增强}//改动4:需要新增⼀个⼝红售卖类@Overridepublic void saleLipstick(String color) {doSomethingBefore();//前置增强lipstickFactory.saleLipstick(color);doSomethingAfter();//后置增强}private void doSomethingAfter() {System.out.println("提供快递服务⼀条龙");}private void doSomethingBefore() {System.out.println("根据您的需求进⾏市场调研");}main{....}}可以看出⼀共有四处改动,所以静态代理的弊端就是,我么如果每增加⼀个代理对象,代理类就需要在原有基础上有很⼤的改动。
SpringAOP拦截-三种方式实现自动代理详解
SpringAOP拦截-三种⽅式实现⾃动代理详解这⾥的⾃动代理,我讲的是⾃动代理bean对象,其实就是在xml中让我们不⽤配置代理⼯⼚,也就是不⽤配置class为org.springframework.aop.framework.ProxyFactoryBean的bean。
总结了⼀下⾃⼰⽬前所学的知识。
发现有三种⽅式实现⾃动代理⽤Spring⼀个⾃动代理类DefaultAdvisorAutoProxyCreator:<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" data-filtered="filtered"></bean>例如:原来不⽤⾃动代理的配置⽂件如下:<!--?xml version="1.0" encoding="UTF-8"?--><beans xmlns="https:///schema/beans" xmlns:context="https:///schema/context" xmlns:tx="https:///schema/tx" xmlns:xsi="https:///2001/XMLSchema-instance" xsi:schem https:///schema/context https:///schema/context/spring-context-4.3.xsdhttps:///schema/tx https:///schema/tx/spring-tx-4.3.xsd"><!-- 代理前原对象 --><bean class="cn.hncu.xmlImpl.Person" id="person"></bean><!-- 切⾯ = 切点+通知 --><bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor"><!-- 切点 --><property name="patterns"><list><value>.*run.*</value></list></property><!-- 通知-由我们写,实际代理动作 --><property name="advice"><bean class="cn.hncu.xmlImpl.AroundAdvice" id="advice"></bean></property></bean><!-- 代理⼯⼚ --><bean class="org.springframework.aop.framework.ProxyFactoryBean" id="personProxied"><!-- 放⼊原型对象 --><property name="target" ref="person"></property><!-- 放⼊切⾯ --><property name="interceptorNames"><list><value>advisor</value></list></property></bean></beans>现在改⽤⾃动代理,如下配置:<beans ...=""><!-- 代理前原对象 --><bean class="cn.hncu.xmlImpl.Person" id="person"></bean><!-- 切⾯ = 切点+通知 --><bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="advisor"><!-- 切点 --><property name="patterns"><list><value>.*run.*</value></list></property><!-- 通知-由我们写,实际代理动作 --><property name="advice"><bean class="cn.hncu.xmlImpl.AroundAdvice" id="advice"></bean></property></bean><!-- ⾃动代理 --><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean></beans>测试⽅法@Test//⾃动代理public void demo4(){ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/hncu/xmlImpl/4.xml");//我们直接在这⾥获取Person对象就可以了,因为在最开始xml⽂件newPerson对象后,Spring就已经帮我们代理了!Person p =ctx.getBean(Person.class);p.run();p.say();}相对于前⾯,也就是把代理⼯⼚部分换成⾃动代理了。
动态代理(Dynamic Proxy) Servlet
动态代理(Dynamic Proxy) Servlet从JDK1.3开始,Java就引入了动态代理的概念。
动态代理(Dynamic Proxy)可以帮助你减少代码行数,真正提高代码的可复用度。
例如,你不必为所有的类的方法里面都写上相同的Log代码行,取而代之的从JDK1.3开始,Java就引入了动态代理的概念。
动态代理(Dynamic Proxy)可以帮助你减少代码行数,真正提高代码的可复用度。
例如,你不必为所有的类的方法里面都写上相同的Log代码行,取而代之的是实用类的动态代理类。
当然,这种便利是有条件的。
本文简单介绍Java动态代理的原理,并实现一个被代理的Servlet创建,和调用的过程。
1.代理模式(Proxy Pattern)在JDK1.3以前,代理模式就已流行,所以得代理模式是生成一个和类相同接口的代理类,用户通过使用代理类来封装某个实现类。
如图1,其目的是加强实现类的某个方法的功能,而不必改变原有的源代码。
2.动态代理(Dynamic Proxy)随着Proxy的流行,Sun把它纳入到JDK1.3实现了Java的动态代理。
动态代理和普通的代理模式的区别,就是动态代理中的代理类是由ng.reflect.Proxy类在运行期时根据接口定义,采用Java反射功能动态生成的。
和ng.reflect.InvocationHandler结合,可以加强现有类的方法实现。
如图2,图中的自定义 Handler实现InvocationHandler接口,自定义Handler实例化时,将实现类传入自定义Handler对象。
自定义 Handler需要实现invoke方法,该方法可以使用Java反射调用实现类的实现的方法,同时当然可以实现其他功能,例如在调用实现类方法前后加入Log。
而Proxy类根据Handler和需要代理的接口动态生成一个接口实现类的对象。
当用户调用这个动态生成的实现类时,实际上是调用了自定义 Handler的invoke方法。
SpringAOP源码
SpringAOP源码WARINGSpring 5.x 中 AOP 默认依旧使⽤ JDK 动态代理。
SpringBoot 2.x 开始,为了解决使⽤ JDK 动态代理可能导致的类型转化异常⽽默认使⽤ CGLIB。
在 SpringBoot 2.x 中,如果需要默认使⽤ JDK 动态代理可以通过配置项spring.aop.proxy-target-class=false来进⾏修改,proxyTargetClass配置已⽆效。
1.注册加载Spring.factories中AopAutoConfiguration配置类// proxyBeanMethods属性默认值是true,也就是说该配置类会被代理(CGLIB),在同⼀个配置⽂件中调⽤其它被@Bean注解标注的⽅法获取对象时会直接从IOC容器之中获取;// 如果设置为false,每次调⽤@Bean标注的⽅法获取到的对象是⼀个新的对象@Configuration(proxyBeanMethods = false)// name 与 prefix 组合使⽤组成完整属性名称,与value不可同时存在// havingValue ⽐较获取的属性值与havingValue给定的值是否相同,相同才加载配置类// matchIfMissing 缺少 property 时是否加载,如果为true,没有该property属性也会正常加载,反之报错@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)public class AopAutoConfiguration {@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Advice.class)static class AspectJAutoProxyingConfiguration {// JDK代理@Configuration(proxyBeanMethods = false)@EnableAspectJAutoProxy(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",matchIfMissing = false)static class JdkDynamicAutoProxyConfiguration {}// CGLIB代理@Configuration(proxyBeanMethods = false)@EnableAspectJAutoProxy(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)static class CglibAutoProxyConfiguration {}}@Configuration(proxyBeanMethods = false)// 当项⽬⾥没有 aspectjweaver 的依赖的时候⽣效@ConditionalOnMissingClass("org.aspectj.weaver.Advice")@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)static class ClassProxyingConfiguration {ClassProxyingConfiguration(BeanFactory beanFactory) {if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}}}}@EnableAspectJAutoProxy(proxyTargetClass = false)@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AspectJAutoProxyRegistrar.class)public @interface EnableAspectJAutoProxy {//true: 使⽤CGLIB基于类创建代理;false: 使⽤java接⼝创建代理boolean proxyTargetClass() default false;// 是否通过aop框架暴露该代理对象,aopContext能够访问.boolean exposeProxy() default false;}AspectJAutoProxyRegistrar.classclass AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 注册bean : AnnotationAwareAspectJAutoProxyCreatorAopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);// 获取注解 @EnableAspectJAutoProxy 的属性,并设置为Bean Definition的属性AnnotationAttributes enableAspectJAutoProxy =AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if (enableAspectJAutoProxy != null) {if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}}AnnotationAwareAspectJAutoProxyCreator.classAnnotationAwareAspectJAutoProxyCreator: ->AspectJAwareAdvisorAutoProxyCreator ->AbstractAdvisorAutoProxyCreator ->AbstractAutoProxyCreator implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware //关注后置处理器(在bean初始化完成强做的事情)、⾃动装配BeanFactory在执⾏ ConfigurationClassPostProcessor 的 processConfigBeanDefinitions 中会执⾏AspectJAutoProxyRegistrar来创建AnnotationAwareAspectJAutoProxyCreator BeanDefinition,但并没有实例化和初始化该对象。
- 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();