当前位置: 首页 > news >正文

个人网站可以做百度推广么/东莞建设企业网站

个人网站可以做百度推广么,东莞建设企业网站,深圳福田住房和建设局网站,广州营销型网站最近花了点时间学习了一下Spring Aop的内容,到此简单做一下笔记。如果存在错误还望多多指教。 概念 所谓的Aop就是Aspect Oriented Programming,即面向切面编程。对于Aop存在一个组织AOP Alliance,该组织制定了一下跟Aop有关的标准&#xff…

最近花了点时间学习了一下Spring Aop的内容,到此简单做一下笔记。如果存在错误还望多多指教。

 

概念

所谓的Aop就是Aspect Oriented Programming,即面向切面编程。对于Aop存在一个组织AOP Alliance,该组织制定了一下跟Aop有关的标准,制定的只是标准,没有实现。通常在Aop中主要有如下术语:

1:Aspect是切面,是面向切面编程的一个抽象,例如面向对象编程中抽象的Class。Aspect由Pointcut与Advice组成。
2:JoinPoint,是切入点,例如对系统的login方法切入记录日志功能,此时login方法就是切入点。
3:Pointcut,切面,是用于描述切入点的一个表达式。例如:execution(* com.javartisan.spring.jdbc.service..*.*(..) 就是一个切面,该表达式是joinpoint集合的抽象表示,表述的是该表下面的所有方法都是joinpoint。
4:Advice,是切入逻辑,也就是增强的逻辑。例如对于login方法添加记录日志功能,记录日志的功能就是advice。
5:织入:将Advice添加到Joinpoint所在位置就是织入。
6:织入器,就是负责将Advice织入到Joinpoint位置的工具。在Spring中为ProxyFactory。

如果上面概念比较难懂,可以简单看一下下面的简单类比,例如你所居住的小区,如果物业需要对小区内每个家庭进行出入等登记,此时登记逻辑就是Advice。由于一些原因物业可能只需要对小区内楼号是奇数的居民进行登记,此时,奇数楼号就是Pointcut,而奇数楼号里面的每一个家庭的出入就是Joinpoint。此时对应的Aspect定义伪代码如下:

aspect 小区出入登记Aspect{point :所居住的楼号是奇数advice:对居民进行出入登记
}

Spring中的Aop

在Spring中Aop有两种实现方式,分别是基于JDK动态代理的实现方式(基于接口的子类实现方式),还有就是基于Cglib字节码生成子类的动态代理。在Spring实现类分别是:JdkDynamicAopProxy与CglibAopProxy,这两个实现类都继承至AopProxy,继承图:

其中的ObjenesisCglibAopProxy是解决Cglib代理实例化代理类时无合适构造器失败的问题,如果不同可以先了解一下Objenesis类库的作用,之后就会很容易理解。可以参考:Objenesis入门参考。本文主要简单记录一下Spring Aop是如何基于JDK代理实现的。

 

JDK动态代理实现思路

JDK动态代理实现主要是基于JDK的两个类分别是:InvocationHandler与Proxy两个类;通过这两个名字就很容易理解他们的职责。InvocationHandler翻译为中文名字是调用处理器,其实就是方法调用处理器,职责就是负责方法调用的,该类只有一个方法:

方法都三个参数,第一个参数为代理,第二个参数为要调用的方法,第三个参数为方法的参数,因此在我们实现此类时候需要将targetObject实例set到此类中作为一个成员变量用于方法调用,而我们的增强逻辑也就是在invoke方法中实现。另一个类Proxy就是代理,它负责生成代理类暴露出去供方法调用。具体可以参考:JDK动态代理。

 

Spring  JdkDynamicAopProxy实现

测试代码:

import com.javartisan.spring.advised.listener.CustomAdvisedSupportListener;
import com.javartisan.util.Utils;
import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;
import sun.misc.Unsafe;import java.io.IOException;
import java.lang.reflect.Field;/*** Unit test for simple ProxyFactory.*/
public class ProxyFactoryTest {private ProxyFactory proxyFactory;@Beforepublic void init() {StudentService target = new StudentServiceImpl();proxyFactory = new ProxyFactory(target);// 添加一个ListenerproxyFactory.addListener(new CustomAdvisedSupportListener());}@Testpublic void testGetProxyJdk() throws IOException {// 将当前的代理暴露到ThreadLocal中proxyFactory.setExposeProxy(true);proxyFactory.setInterfaces(StudentService.class);//aspect (in spring called advisor)NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();//adviceadvisor.setAdvice(new StudentAdvice());//pointcutadvisor.setMappedName("add");//添加切面到织入器proxyFactory.addAdvisor(advisor);StudentService proxy = (StudentService) proxyFactory.getProxy();Utils.generateProxyClassToFile(proxy.getClass(), "StudentService");// 调用joinpoint方法proxy.add();}}

代理类是由ProxyFactory生成的,前面概念中也提到ProxyFactory是Spring Aop的织入器。继承结构:

接下来重点跟踪代码:StudentService proxy = (StudentService) proxyFactory.getProxy()看看内部,getProxy()方法内部主要做如下几件事:

1:创建一个AopProxy,调用ProxyCreatorSupport#createAopProxy方法完成AopProxy的创建:

	/*** Subclasses should call this to get a new AOP proxy. They should <b>not</b>* create an AOP proxy with {@code this} as an argument.*/protected final synchronized AopProxy createAopProxy() {if (!this.active) {//初始化工作,主要完成Listener的注册,可以通过添加Listener监听变化activate();}//创建代理return getAopProxyFactory().createAopProxy(this);}

获取到AopProxyFactory之后调用createAopProxy方法创建代理,也就是调用DefaultAopProxyFactory#createAopProxy方法:

	@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}

这里面有比较了解一下方法参数AdvisedSupport:

AdvisedSupport继承至ProxyConfig与Advised,这两个父类都是AopProxy的配置信息类,因此AdvisedSupport中就包含这AopProxy的配置信息,例如Advisor(Aspect),targetSource(targetObject)等。

既然DefaultAopProxyFactory#createAopProxy方法有AopProxyConfig信息当然就可以根据targetObject属性创建Jdk或者cglib的代理了。这里面我们跟踪的是JDK的Aop实现,因此最终会创建一个JdkDynamicAopProxy。到此AopProxy的具体实现类JdkDynamicAopProxy就完成了创建。

2:然后调用AopProxy#getProxy()获取代理,在JDK动态代理中AopProxy对应的是JdkDynamicAopProxy#getProxy方法:

	@Overridepublic Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());}// 查找代理接口,基于接口生成代理子类Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);//使用JDK的Proxy完成代理类创建return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}

java.lang.reflect.Proxy#newProxyInstance方法三个参数:类加载器,代理接口以及InvocationHandler方法调用器。在Spring的JdkDynamicAopProxy中该类已经实现InvocationHandler,继承图如下:

因此第三个参数直接传入this即可。到此也就完成了代理类的创建,生成的代理类代码可以借助Arthas工具导出来,生成代理类代码:

package com.sun.proxy;import com.javartisan.spring.StudentService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;/*** 实现了我们的StudentService接口*/
public final class $Proxy0 extends Proxy implements StudentService,SpringProxy,Advised {// joinpoint方法成员变量private static Method m3;private static Method m1;private static Method m8;private static Method m10;private static Method m22;private static Method m17;private static Method m14;private static Method m4;private static Method m11;private static Method m23;private static Method m24;private static Method m0;private static Method m15;private static Method m20;private static Method m7;private static Method m25;private static Method m2;private static Method m26;private static Method m9;private static Method m18;private static Method m5;private static Method m6;private static Method m19;private static Method m12;private static Method m21;private static Method m16;private static Method m13;// 反射获取方法初始化成员变量static {try {// 此方法就是我们的joinpoint方法,也就是需要增强的方法m3 = Class.forName("com.javartisan.spring.StudentService").getMethod("add", new Class[0]);m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m8 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", Class.forName("org.springframework.aop.Advisor"));m10 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isExposeProxy", new Class[0]);m22 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isProxyTargetClass", new Class[0]);m17 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", Integer.TYPE);m14 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getProxiedInterfaces", new Class[0]);m4 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", Class.forName("org.springframework.aop.Advisor"));m11 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetSource", new Class[0]);m23 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", Integer.TYPE, Class.forName("org.aopalliance.aop.Advice"));m24 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvice", Class.forName("org.aopalliance.aop.Advice"));m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);m15 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isInterfaceProxied", Class.forName("java.lang.Class"));m20 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvice", Class.forName("org.aopalliance.aop.Advice"));m7 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setExposeProxy", Boolean.TYPE);m25 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setTargetSource", Class.forName("org.springframework.aop.TargetSource"));m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);m26 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getTargetClass", new Class[0]);m9 = Class.forName("org.springframework.aop.framework.Advised").getMethod("addAdvisor", Integer.TYPE, Class.forName("org.springframework.aop.Advisor"));m18 = Class.forName("org.springframework.aop.framework.Advised").getMethod("removeAdvisor", Class.forName("org.springframework.aop.Advisor"));m5 = Class.forName("org.springframework.aop.framework.Advised").getMethod("indexOf", Class.forName("org.aopalliance.aop.Advice"));m6 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isFrozen", new Class[0]);m19 = Class.forName("org.springframework.aop.framework.Advised").getMethod("replaceAdvisor", Class.forName("org.springframework.aop.Advisor"), Class.forName("org.springframework.aop.Advisor"));m12 = Class.forName("org.springframework.aop.framework.Advised").getMethod("setPreFiltered", Boolean.TYPE);m21 = Class.forName("org.springframework.aop.framework.Advised").getMethod("toProxyConfigString", new Class[0]);m16 = Class.forName("org.springframework.aop.framework.Advised").getMethod("getAdvisors", new Class[0]);m13 = Class.forName("org.springframework.aop.framework.Advised").getMethod("isPreFiltered", new Class[0]);return;}catch (NoSuchMethodException noSuchMethodException) {throw new NoSuchMethodError(noSuchMethodException.getMessage());}catch (ClassNotFoundException classNotFoundException) {throw new NoClassDefFoundError(classNotFoundException.getMessage());}}public final void add() {try {//h就是我们的InvocationHandler,也就是本文所说的方法调用器this.h.invoke(this, m3, null);return;}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}//忽略其他与本文无关的方法
}

到此已经彻底完成了代理类的生成,接下来就了解一下如何对joinpoint方法进行增强的。

JoinPoint的增强实现

到此为止代理类已经生成,最终业务代码可以借助代理类进行方法调用已完成增强,增强的标准接口继承结构如下:

Advice就是aopalliance制定的标准接口。对于示例代码的增强逻辑代码如下:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;public class StudentAdvice implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("StudentAdvice start .");Object obj = invocation.proceed();System.out.println("StudentAdvice end .");return obj;}
}

 

接下来看一下如何完成的增强。在本文中joinpoint为StudentService#add()方法,因此当我们调用add方法时候会触发代理类的add方法,即如上的add方法,最终进入到JdkDynamicAopProxy#invoke方法中,精简代码如下:

/*** Implementation of {@code InvocationHandler.invoke}.* <p>Callers will see exactly the exception thrown by the target,* unless a hook method throws an exception.*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {MethodInvocation invocation;Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Class<?> targetClass = null;Object target = null;// 忽略equal与hashcode方法的处理Object retVal;//是否暴露代理到线程局部变量,如果暴露的话需要设置expose参数//使用场景,如果targetObject内部调用本类的其他方法还需增强的话。//需要使用AopContext#currentProxy获取this实例对应的代理对象调用if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// May be null. Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.//TargetSource是spring对TargetObject的一种封装表示target = targetSource.getTarget();if (target != null) {targetClass = target.getClass();}// Get the interception chain for this method.//获取待增强的所有 adviceList<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// Check whether we have any advice. If we don't, we can fallback on direct// reflective invocation of the target, and avoid creating a MethodInvocation.if (chain.isEmpty()) {//没有增强,直接调用target方法// We can skip creating a MethodInvocation: just invoke the target directly// Note that the final invoker must be an InvokerInterceptor so we know it does// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);} else {// We need to create a method invocation...//有增强,需要完成增强的逻辑调用//ReflectiveMethodInvocation负责完成增强逻辑与最终targetObject方法的封装invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor chain.//通过增强逻辑与最终targetObject方法的封装对象最终完成调用retVal = invocation.proceed();}//处理返回值// Massage return value if necessary.Class<?> returnType = method.getReturnType();if (retVal != null && retVal == target && returnType.isInstance(proxy) &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {// Special case: it returned "this" and the return type of the method// is type-compatible. Note that we can't help if the target sets// a reference to itself in another returned object.retVal = proxy;} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);}return retVal;} finally{if (target != null && !targetSource.isStatic()) {// Must have come from TargetSource.targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.// 如果开启了暴露当前代理到线程局部变量的话,最后需要还原之前的代理AopContext.setCurrentProxy(oldProxy);}}
}

JdkDynamicAopProxy中含有所有的Aop信息,因此就可以完成最终方法的增强调用。不过在JdkDynamicAopProxy#invoke中进行了增强advice与targetObject方法的封装,封装为:ReflectiveMethodInvocation,ReflectiveMethodInvocation#proceed方法才是最后的方法调用结束。ReflectiveMethodInvocation继承结构如下:

上层的接口都是Aopalliance的标准接口,下面是Spring进行的实现。 ReflectiveMethodInvocation#proceed源码如下:

    @Overridepublic Object proceed() throws Throwable {//	We start with an index of -1 and increment early.if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {// 最终完成targetObject的方法调用,也就是joinpoint方法调用return invokeJoinpoint();}//递归调用增强的chain//this.interceptorsAndDynamicMethodMatchers就是advice组成的调用链Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {return dm.interceptor.invoke(this);} else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.return proceed();}} else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.//调用advice,也就是调用增强逻辑return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}

到此也就结束了,完成了从代理对象的生成以及借助代理对象调用增强逻辑以及最终的targetObject的方法。

http://www.lbrq.cn/news/1291105.html

相关文章:

  • 怎样制作时时彩网站做 裙 o/个人接外包的网站
  • 潍坊网站制作套餐/腾讯朋友圈广告投放价格
  • 网站建设基本流程是什么/百度网盘官网登陆入口
  • wap网站设计方案/百度词条搜索排行
  • mac可以做网站开发吗/湖北seo推广
  • 怎么做一种网站为别人宣传/西安网络优化哪家好
  • 网站flash动画效果代码/怎么提升关键词的质量度
  • 女人与狗做视频网站/四川游戏seo整站优化
  • 电商网站开发会遇到哪些问题/指数型基金
  • 符合三网标准的网站建设/网络营销咨询公司
  • 小伙做网色网站/b站推广软件
  • 山东各地网站备案/服务营销策划方案
  • 做网站的基本要求/长沙弧度seo
  • 个人作品集网站模板免费下载/软件工程培训机构哪家好
  • iis5.1发布网站/企业宣传片
  • 腾讯企业邮箱容量/广州软件系统开发seo推广
  • 临沂专业做网站/网络推广公司运作
  • 网站开发的在淘宝上是什么类目/域名停靠
  • 自己做的网站怎么设置关键词/互联网营销师资格证
  • 品牌推广型网站/谷歌浏览器 安卓下载
  • 建设导航网站费用/软文推广经典案例
  • 学生制作网页教程/seo和sem是什么
  • wordpress网站不收录/淄博新闻头条最新消息
  • 什么秀网站做效果图/学生个人网页制作
  • 东莞凤岗网站建设/seo职位具体做什么
  • 武汉教育网站建设公司/农产品网络营销方案
  • 成都网站建设易维达好/惠州seo外包服务
  • 张家港手机网站设计/网站数据查询
  • 济南高端网站制作公司/招聘网站排名
  • 应该选用什么口罩/重庆seo推广服务
  • Linux文件系统理解1
  • [3-02-02].第04节:开发应用 - RequestMapping注解的属性2
  • Springboot + MyBatis-Plus + PageHelper 分页性能混合优化方案
  • Apache Ignite 中 WHERE 子句中的子查询(Subqueries in WHERE Clause)的执行方式
  • 感知机-梯度下降法
  • 对粒子群算法的理解与实例详解