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

网站安全检测wordpress 标题重复

网站安全检测,wordpress 标题重复,常德seo技术,做学校网站会下线吗Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…

Spring源码阅读目录

第一部分——IOC篇

第一章 Spring之最熟悉的陌生人——IOC
第二章 Spring之假如让你来写IOC容器——加载资源篇
第三章 Spring之假如让你来写IOC容器——解析配置文件篇
第四章 Spring之假如让你来写IOC容器——XML配置文件篇
第五章 Spring之假如让你来写IOC容器——BeanFactory和FactoryBean
第六章 Spring之假如让你来写IOC容器——Scope和属性填充
第七章 Spring之假如让你来写IOC容器——属性填充特别篇:SpEL表达式
第八章 Spring之假如让你来写IOC容器——拓展篇
第九章 Spring之源码阅读——环境搭建篇
第十章 Spring之源码阅读——IOC篇

第二部分——AOP篇

第十一章 Spring之不太熟的熟人——AOP
第十二章 Spring之不得不了解的内容——概念篇
第十三章 Spring之假如让你来写AOP——AOP联盟篇
第十四章 Spring之假如让你来写AOP——雏形篇
第十五章 Spring之假如让你来写AOP——Joinpoint(连接点)篇
第十六章 Spring之假如让你来写AOP——Pointcut(切点)篇
第十七章 Spring之假如让你来写AOP——Advice(通知)上篇
第十八章 Spring之假如让你来写AOP——Advice(通知)下篇
第十九章 Spring之假如让你来写AOP——番外篇:Spring早期设计
第二十章 Spring之假如让你来写AOP——Aspect(切面)篇
第二十一章 Spring之假如让你来写AOP——Weaver(织入器)篇
第二十二章 Spring之假如让你来写AOP——Target Object(目标对象)篇


文章目录

  • Spring源码阅读目录
    • 第一部分——IOC篇
    • 第二部分——AOP篇
  • 前言
  • 尝试动手写IOC容器
      • 第十六版 AOP雏形
          • 哪些地方可以增强?
          • 如何找到这些地方?
          • 找到后要怎么增强?
          • 多个增强如何管理?
          • 如何对其进行增强?
  • 总结


前言

    对于Spring一直都是既熟悉又陌生,说对它熟悉吧,平时用用没啥问题,但面试的时候被问的一脸懵逼,就很尴尬,都不好意思在简历上写着熟悉Spring了
在这里插入图片描述

    所以决定花点时间研究研究Spring的源码。主要参考的书籍是:《Spring源码深度解析(第2版)》、《Spring揭秘》、《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》


    书接上回,在上篇 第十三章 Spring之假如让你来写AOP——AOP联盟篇 中,A君 先把 AOP联盟 规范的接口定义好了。接下来看看 A君 会有什么骚操作吧

尝试动手写IOC容器

    出场人物:A君(苦逼的开发)、老大(项目经理)

    背景:老大要求A君在一周内开发个简单的 IOC容器

    前情提要: 昨天,A君 定义了 AOP联盟 规范的接口 。。。

第十六版 AOP雏形

    俗话说:人无远虑,必有近忧。 这句话用来描述 A君 此时的状态再合适不过了。 A君 现在 看着这一堆接口,一脸懵逼,这要怎么继续。纠结了良久,A君 按照之前的思路走:

  1. 哪些地方可以增强?
  2. 如何找到这些地方?
  3. 找到后要怎么增强?
  4. 多个增强如何管理?
  5. 如何对其进行增强?
哪些地方可以增强?

    目标既然已经确定,A君 开始着手准备实现 Joinpoint(连接点) 相关内容。按照之前 A君 了解到的知识:Joinpoint(连接点) 就是定义 AOP 对目标对象可以增强的地方。 A君 的计划是实现方法增强即可,也就是 Joinpoint(连接点) 就是方法,即需要实现 MethodInvocation 接口,这点不再有任何疑虑。确定完需要实现的接口,接着还要确定一下类需要实现的功能,这不经让 A君 一阵皱眉。Joinpoint(连接点) 无疑是方法执行的地方,如果仅仅执行目标方法,显然不够。需要加上 Advice(通知),那么有多个 Advice(通知) 怎么解决?

    思来想去,A君 决定让 Joinpoint(连接点) 接收所有 Advice(通知) ,然后通过链式调用去执行每一个 Advice(通知)。思路清晰后,A君 撸袖子开干,定义 ReflectiveMethodInvocation 类,代码如下:

import com.hqd.ch03.v16.aopalliance.intercept.MethodInterceptor;
import com.hqd.ch03.v16.aopalliance.intercept.MethodInvocation;import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;/*** 连接点类,用以执行通知及目标方法*/
public class ReflectiveMethodInvocation implements MethodInvocation {private Object proxy;private Method method;private Object[] args;private List<MethodInterceptor> mis;private int currentInterceptorIndex = -1;public ReflectiveMethodInvocation(Object proxy, Method method,Object[] args, List<MethodInterceptor> mis) {this.proxy = proxy;this.method = method;this.args = args;this.mis = mis;}@Nonnull@Overridepublic Method getMethod() {return method;}@Nonnull@Overridepublic Object[] getArguments() {return args;}@Nullable@Overridepublic Object proceed() throws Throwable {/*** 链式调用通知*/if (mis.size() - 1 == currentInterceptorIndex) {return getMethod().invoke(proxy, args);}MethodInterceptor methodInterceptor = this.mis.get(++currentInterceptorIndex);return methodInterceptor.invoke(this);}@Nullable@Overridepublic Object getThis() {return proxy;}@Nonnull@Overridepublic AccessibleObject getStaticPart() {return null;}
}
如何找到这些地方?

    “现在 Joinpoint(连接点) 有了,还需要一个可以找到对应 Joinpoint(连接点)Pointcut(切点) ” ,A君 思忖。对于 Pointcut(切点)A君 之前用 Spring 也有接触过,类似于:execution( .test(…)) ,这块内容 Spring 也并非自己实现,而是使用 AspectJ。想到这里,A君 决定也站在巨人的肩膀上,使用 AspectJ 实现对应的 Joinpoint(连接点) 匹配。那么 Pointcut(切点) 的就简单了,接收对应的表达式,调用 AspectJ 进行匹配即可。捋清楚之后,A君 开始撸代码,定义 AspectJExpressionPointcut 类,其代码如下:

import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParameter;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.Set;/*** 切点表达式匹配*/
public class AspectJExpressionPointcut {private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();static {/*** 定义 AspectJ 匹配器*/SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);}/*** 切点表达式*/private String expression;private String[] pointcutParameterNames = new String[0];private Class<?>[] pointcutParameterTypes = new Class<?>[0];public AspectJExpressionPointcut(String expression) {this.expression = expression;}public PointcutExpression buildPointcutExpression() {PointcutParser parser = initializePointcutParser(Thread.currentThread().getContextClassLoader());PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];/*** 匹配对应的参数*/for (int i = 0; i < pointcutParameters.length; i++) {pointcutParameters[i] = parser.createPointcutParameter(this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);}return parser.parsePointcutExpression(getExpression(),null, pointcutParameters);}/*** 初始化切点匹配器** @param classLoader* @return*/private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {PointcutParser parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, classLoader);return parser;}public String getExpression() {return this.expression;}
}
找到后要怎么增强?

注:此处理解有误,Spring 应该由于历史原因,才有不同的实现。这里大家别信,看个乐呵。后边有专门的篇章解释

    在找到 Joinpoint(连接点) 之后,接下来要解决的就是怎么增强目标方法 。 前置、后置、环绕、异常增强 这些都是耳熟能详的词,但是实现上却有些不一样。首先是 Before Advice(前置通知)After Returning Advice,这两个可以直接调用增强方法,不需要特殊的操作,而 After Throwing AdviceAfter (Finally) AdviceAround Advice(环绕通知) 却不一样,需要对方法进行更细致的操作。故而 A君 把他们分成两种,Before Advice(前置通知)After Returning Advice 直接拓展 Advice 接口,A君 照猫画虎,定义一个 BeforeAdvice 接口,作为 Before Advice(前置通知) 的标记接口,代码如下:

import com.hqd.ch03.v16.aopalliance.aop.Advice;/*** 前置通知标记接口*/
public interface BeforeAdvice extends Advice {}

只有标记接口,显然是干不了任何事的,所以还需要定义一个真正干活的接口—— MethodBeforeAdvice,代码如下:

import javax.annotation.Nullable;
import java.lang.reflect.Method;public interface MethodBeforeAdvice extends BeforeAdvice {void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
}

接口有了,按照惯例,接下来就是具体实现了,不急不急。A君 经过一番观察,发现这些 Advice(通知) 都是一个套路,虽然有分前后置,但是都是先确定 Pointcut(切点) 是否匹配,在执行相应的方法。咦?有公共代码,那么他就要来了,没错,就是他——抽象类。A君 定义 AbstractAspectJAdvice 类,代码如下:

import com.hqd.ch03.v16.aopalliance.aop.Advice;import javax.annotation.Nonnull;
import java.lang.reflect.Method;public abstract class AbstractAspectJAdvice implements Advice {private Method aspectJAdviceMethod;private Object aspect;private AspectJExpressionPointcut pointcut;public AbstractAspectJAdvice(AspectJExpressionPointcut pointcut, Method aspectJAdviceMethod, Object aspect) {this.aspectJAdviceMethod = aspectJAdviceMethod;this.aspect = aspect;this.pointcut = pointcut;}protected void invokeAdviceMethod(@Nonnull Method method) {if (match(method)) {try {aspectJAdviceMethod.invoke(aspect);} catch (Exception e) {throw new RuntimeException(e);}}}/*** 判断是否匹配** @param method* @return*/protected boolean match(Method method) {return pointcut.buildPointcutExpression().matchesMethodExecution(method).alwaysMatches();}
}

提取完公共代码,接下来就要回到正题——实现 MethodBeforeAdvice。不过这玩意确实也没有什么东西,直接调用父类方法即可。A君 定义 AspectJMethodBeforeAdvice 类,代码如下:

import com.hqd.ch03.v16.aop.framework.MethodBeforeAdvice;import javax.annotation.Nullable;
import java.lang.reflect.Method;public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice {public AspectJMethodBeforeAdvice(AspectJExpressionPointcut pointcut, Method aspectJAdviceMethod, Object aspect) {super(pointcut, aspectJAdviceMethod, aspect);}@Overridepublic void before(Method method, Object[] args, @Nullable Object target) throws Throwable {invokeAdviceMethod(method);}
}

“咦?不太对劲。” A君 警觉。在定义 ReflectiveMethodInvocation 类时,A君 要求通知必须要时 MethodInterceptor 类型,因为只有类型为 MethodInterceptor 整个链式调用才能玩的动,而 AspectJMethodBeforeAdvice 显然不是。没办法,套个马甲把,于是乎,A君 有定义了一个 MethodBeforeAdviceInterceptor 类,适配器?随便了。代码如下:

import com.hqd.ch03.v16.aop.framework.BeforeAdvice;
import com.hqd.ch03.v16.aop.framework.MethodBeforeAdvice;
import com.hqd.ch03.v16.aopalliance.intercept.MethodInterceptor;
import com.hqd.ch03.v16.aopalliance.intercept.MethodInvocation;
import lombok.AllArgsConstructor;import javax.annotation.Nonnull;
import javax.annotation.Nullable;@AllArgsConstructor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice {private final MethodBeforeAdvice advice;@Nullable@Overridepublic Object invoke(@Nonnull MethodInvocation mi) throws Throwable {advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());return mi.proceed();}
}

OK,搞定。这么一来, Joinpoint(连接点) 的链式调用就玩的转了。接下来 AfterReturningAdvice 也是同理,限于篇幅,A君 就不再列举了

    After Throwing AdviceAfter (Finally) Advice 这类通知需要对方法进行更精细的控制,所以需要实现 MethodInterceptor,而不是直接实现 AdviceA君 先对 After (Finally) Advice 进行实现,见名知意,这个应该是在 finally 代码块里面实现的, A君 定义 AspectJAfterAdvice 类,代码如下:

import com.hqd.ch03.v16.aop.framework.AfterAdvice;
import com.hqd.ch03.v16.aopalliance.intercept.MethodInterceptor;
import com.hqd.ch03.v16.aopalliance.intercept.MethodInvocation;import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Method;public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {public AspectJAfterAdvice(AspectJExpressionPointcut pointcut, Method aspectJAdviceMethod, Object aspect) {super(pointcut, aspectJAdviceMethod, aspect);}@Nullable@Overridepublic Object invoke(@Nonnull MethodInvocation mi) throws Throwable {try {return mi.proceed();} finally {invokeAdviceMethod(mi.getMethod());}}
}

After Throwing Advice 自然就是在 catch 代码块执行了,只有异常时才执行,代码类似,A君 也不列举了

多个增强如何管理?

    管理 Advice(通知) 这部分内容就比较好实现了,无非定义一个管理类,可以对 Advice(通知) 进行增删查改排序就行了,这玩意难不倒 A君A君 直接定义 AdvisedSupport 类,让它对 Advice(通知) 进行管理,代码如下:

import com.hqd.ch03.v16.aopalliance.intercept.MethodInterceptor;
import org.apache.commons.collections4.CollectionUtils;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;/*** advice管理类*/
public class AdvisedSupport {private List<MethodInterceptor> advisors = new ArrayList<>();public void addAdvisors(Collection<MethodInterceptor> advisors) {if (CollectionUtils.isNotEmpty(advisors)) {this.advisors.addAll(advisors);}}public void addAdvisor(MethodInterceptor advisor) {if (advisor != null) {this.advisors.add(advisor);}}public List<MethodInterceptor> getAdvisors() {return advisors;}
}
如何对其进行增强?

    现在万事俱备,只剩最后一部分内容了,如何把通知和目标方法进行关联?先创建代理对象,这一步毋庸置疑。但是要怎么对代理对象进行增强,嘿嘿,这个简单,老套路,套个马甲就行了。给代理类添加个默认的拦截器,让它去执行整个通知链路。思量完毕,A君 先定义 ProxyFactory 类,作为代理工厂,用以创建代理对象,并创建默认的方法拦截器。代码如下:


import lombok.AllArgsConstructor;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.io.Serializable;
import java.lang.reflect.Method;@AllArgsConstructor
public class ProxyFactory extends AdvisedSupport {private Class<?> superClass;private Object target;private Method method;public Object getProxy() {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(superClass);/*** 添加默认拦截器,执行增强*/enhancer.setCallbacks(new Callback[]{new DynamicAdvisedInterceptor(this, target, method)});return enhancer.create();}@AllArgsConstructorprivate static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private AdvisedSupport advisedSupport;private Object target;private Method method;@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {ReflectiveMethodInvocation rmi = new ReflectiveMethodInvocation(target, this.method, null, advisedSupport.getAdvisors());return rmi.proceed();}}
}

至此,A君 所有的步骤都已经实现了,现在需要测试一下,来验证自己的努力的成果。测试代码如下:

@Testpublic void v16() throws Throwable {System.out.println("############# 第十六版:aop雏形 #############");AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut("execution(* *.test(..))");Object ap = new AopBean();Method method = AopBean.class.getDeclaredMethod("test");AopTest aop = new AopTest();Method beforeTest = aop.getClass().getDeclaredMethod("beforeTest");Method afterTest = aop.getClass().getDeclaredMethod("afterTest");Method afterReturnTest = aop.getClass().getDeclaredMethod("afterReturnTest");List<MethodInterceptor> list = new ArrayList<>();//前置通知AspectJMethodBeforeAdvice aspectJMethodBeforeAdvice = new AspectJMethodBeforeAdvice(pointcut, beforeTest, aop);MethodBeforeAdviceInterceptor methodBeforeAdviceInterceptor = new MethodBeforeAdviceInterceptor(aspectJMethodBeforeAdvice);list.add(methodBeforeAdviceInterceptor);//后置通知list.add(new AspectJAfterAdvice(pointcut, afterTest, aop));//返回通知AspectJAfterReturningAdvice aspectJAfterReturningAdvice = new AspectJAfterReturningAdvice(pointcut, afterReturnTest, aop);list.add(new AfterReturningAdviceInterceptor(aspectJAfterReturningAdvice));ProxyFactory proxyFactory = new ProxyFactory(AopBean.class, ap, method);proxyFactory.addAdvisors(list);AopBean proxy = (AopBean) proxyFactory.getProxy();proxy.test();

在这里插入图片描述

从结果来看,是符合预期的,A君 打算先给 老大 看下,毕竟 老大 有自己的想法,不是个好糊弄的主。今天先到这里,A君 上传代码,准备下班咯

在这里插入图片描述

总结

    正所谓树欲静而风不止,欲知后事如何,请看下回分解(✪ω✪)

http://www.yayakq.cn/news/218908/

相关文章:

  • 站长工具ip地址查询域名展示型网站建设方案
  • 2017做淘宝客网站还有吗烟台专业做网页的公司
  • 福建高能建设工程有限公司网站app开发公司 上海
  • 网站空间内存网站的优化和推广方案
  • 网站设计制作一般多少钱上海学校网站建设
  • 友创互联网站建设有限公司720全景网站怎么做
  • 福安建设网站wordpress镜像是什么意思
  • 几百的网站网页游戏传奇开服表
  • opencart做视频网站wordpress ajax分页插件
  • php网站开发实用技术练习题百度多久收录网站
  • 做网站怎么带流量东莞网站推广流程
  • 荆州做网站公司网站开发语言比较
  • 网站建设工作部署会达州设计公司
  • 梁山网站建设多少钱正邦设计好进吗
  • 网站设计 psdwordpress 搜索 提示
  • 做这种灰色的网站犯法我电脑做网站局域网怎么访问
  • 建建设网站公司珠海建设网站的公司哪家好
  • 如何看自己网站流量单位做好接种第三针疫苗通知
  • 大型门户网站开发公司盐城网站建设推广
  • 服装设计网站有哪些推荐做直播大秀的平台和网站
  • 我是做化工回收的做哪个网站比较好浙江网站开发公司
  • 盐城做网站找哪家好拟与 合作建设网站 请予审批
  • 为什么亿唐网不做网站做品牌seo软件下载
  • 手机网站建设电话大理市住房和城乡建设局网站
  • 网站备案证书下载失败广州网站设计企业
  • 摄影网站建设策划书长安网站优化公司
  • 四川省建设安全质量监理协会网站贵安新区城乡住房建设厅网站
  • 华大基因 建设公司网站岳阳工程造价信息网
  • 深圳做二维码网站建设深圳装饰装修公司
  • 湖南网站建设公找人做网站排名优化