在开始正文以前,先聊点其它的,本来规划的《Spring AOP实现原理》系列的最后一章节是讲解Spring AOP源码的。刚开始对此也是信心满满的,直到我深刻读了源码以后才发现这事情没有那么简单。java
首先,Spring AOP源码有些多,不够精简,这就给书面讲解形成很大麻烦。其次,彻底基于Spring AOP源码讲解它的实现彷佛也没有太大意义。git
所以我决定另辟蹊径,从Spring AOP的特性和功能发起,而后结合着Spring AOP实现的思路,大体实现一个Spring AOP的架子。github
特别声明:在实现的过程当中,因为篇幅缘由,砍掉了很多优化部分,特别是有关工厂,懒加载,缓存,并发等。spring
从上一章节中,咱们得知了Spring AOP的特性以及其要完成功能,咱们抽取出其中的重点列举一下:express
咱们针对这些特性作一个功能分析,大体有以下功能:设计模式
AOP,主要专一于基于方法的AOP功能实现,分为三个方面:缓存
对象代理,支持JDK和CGLIB两种代理方式,实现根据目标对象(target)生成对应的代理对象并发
配置解析,支持XML和Annotation两种配置方式的解析,实现根据配置解析出对应的Advisor等ide
IoC集成,集成BeanFactory,实现对IoC容器中bean的访问;实现BeanPostProcesser,将配置解析、建立代理对象等归入到bean初始化流程工具
注:咱们看下官网对Advisor的解释:*
An advisor is like a small self-contained aspect that has a single piece of advice.
*Advisor是具备单个Advice以及可使用Pointcut的组合类,能够看做是一个特殊的Aspect。
在列出了Spring AOP功能以后,咱们接下来讨论下功能实现的流程
我把流程简单分为两大部分,建立代理阶段和代理调用阶段,其中前者是由Spring IoC初始化触发的,后者是由程序调用触发的,详细流程参考下图:
Spring IoC容器触发Bean初始化,经过BeanPostProcesser接口
调用BeanPostProcesser接口实现方法postProcessAfterInitialization
进入构建Advisor的流程,经过反射找到全部匹配的Advisor
筛选出符合的Advisor
进入建立代理的流程,将上一个流程中获得的Advisor集合传递给代理对象,而且根据规则判断使用哪一种代理方式
在列出了Spring AOP功能以后,咱们接下来讨论功能的实现部分功能的实现
首先对AspectJ中的概念抽象,咱们简单定义下Aspect、JoinPoint、Advice、Pointcut等类。
public class Aspect {
}
public class JoinPoint {
}
public interface Pointcut {
public String getExpression();
}
public class Advice {
private Method adviceMethod;
private Aspect aspect;
}
复制代码
SpringAOP中引入了Advisor的概念,咱们同时定义一个Advisor类
public class Advisor {
private Advice advice;
private Pointcut pointcut;
private Aspect aspect;
}
复制代码
为了融合AspectJ的表达式,咱们针对Pointcut进一步改造
增长字符串表达式转换为AspectJ的表达式(PointcutExpression)
import org.aspectj.weaver.tools.PointcutExpression;
//....
/** * 转换为AspectJ的切入点表达式 * @return */
public PointcutExpression buildPointcutExpression();
复制代码
引入AspectJ解析类(PointcutParser),实现buildPointcutExpression方法
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
public class AspectJPointcut implements Pointcut {
public String expression;
public AspectJPointcut(String expression) {
this.expression = expression;
}
@Override
public String getExpression() {
return this.expression;
}
@Override
public PointcutExpression buildPointcutExpression() {
PointcutParser parser = PointcutParser
.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution();
return parser.parsePointcutExpression(this.expression);
}
}
复制代码
以上,定义了几个基本类。有的小伙伴会说,为何没有看到BeforeAdvice这些定义呢?这里先卖个关子,等到后面引入方法拦截器的时候再定义。
集成自己比较简单,实现接口BeanPostProcessor和BeanFactoryAware,直接上代码
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
public abstract class AbstractAOPProxyCreator implements BeanPostProcessor, BeanFactoryAware {
//子类可实现
protected void initBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
//获取匹配的Advisor
protected abstract List<Advisor> getMatchedAdvisors();
//建立代理对象
protected abstract Object createProxy(List<Advisor> advisors, Object bean);
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName){
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName){
return bean;
}
}
复制代码
实现了BeanFactoryAware接口的setBeanFactory方法,以及BeanPostProcessor接口的postProcessAfterInitialization方法和postProcessBeforeInitialization方法。
下面咱们引入模板方法设计模式,来制定处理流程:
public Object postProcessAfterInitialization(Object bean, String beanName){
//构建全部Advisor
List<Advisor> advisors = buildAdvisors();
//获取符合的Advisor
advisors = this.getMatchedAdvisors();
//根据获取的Advisor生成代理对象
Object object = createProxy(advisors,bean);
//返回代理对象
return object == null ? bean : object;
}
复制代码
解析配置主要就是用到了反射,找到被@Aspect标记的类,进而找到@Advice,@Pointcut等,最终将这些组合成Advisor实例,实现起来并不复杂,再也不赘述
public class AnnotationParser implements ConfigParser {
//避免重复构建,增长了缓存
private final Map<String, List<Advisor>> cache = new ConcurrentHashMap<>();
@Override
public List<Advisor> parse() {
if(cache != null) {
return getAdvisorsFromCache();
}
//获取全部被@Aspect注解的类
List<Class> allClasses = getAllAspectClasses();
for (Class class1 : allClasses) {
cache.putIfAbsent(class1.getName(), getAdvisorsByAspect(class1));
}
return getAdvisorsFromCache();
}
/** * 根据Aspect类生成Advisor类 * @param class1 * @return */
private List<Advisor> getAdvisorsByAspect(Class class1) {
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(class1)) {
Advisor advisor = getAdvisor(method, class1.newInstance());
advisors.add(advisor);
}
return advisors;
}
}
复制代码
咱们要从全部的Advisor中过滤出来与代理目标Bean相关的,以Bean的方法和Advisor的Pointcut做为过滤条件,这里利用了AspectJ的表达式以及比对工具
import org.aspectj.weaver.tools.ShadowMatch;
/** * 从全部的Advisor中获取匹配的 * @param advisors * @return */
public static List<Advisor> getMatchedAdvisors(Class cls, List<Advisor> advisors) {
List<Advisor> aList = new ArrayList<>();
for (Method method : cls.getDeclaredMethods()) {
for (Advisor advisor : advisors) {
ShadowMatch match = advisor.getPointcut()
.buildPointcutExpression()
.matchesMethodExecution(method);
if(match.alwaysMatches()) {
aList.add(advisor);
}
}
}
return aList;
}
复制代码
咱们定义了一个工厂,代理对象转交给由工厂建立
public class AOPProxyFactory {
public Object getProxyObject(List<Advisor> advisors, Object bean) {
if(isInterface()) {
return new CglibProxyImpl(advisors,bean).getProxyObject();
} else {
return new JdkDynamicProxyImpl(advisors,bean).getProxyObject();
}
}
private boolean isInterface() {
return false;
}
}
复制代码
同时也实现了两种代理方式,JDK Dynamic Proxy和CGLIB,下面逐一讲解下
注:能够先忽略掉方法拦截器链
JDK 实现方式,须要实现InvocationHandler接口,而且在接口方法invoke中实现方法拦截器链的调用
public class JdkDynamicProxyImpl extends AOPProxy implements InvocationHandler {
public JdkDynamicProxyImpl(List<Advisor> advisors, Object bean) {
super(advisors, bean);
}
@Override
protected Object getProxyObject() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), ReflectHelper.getInterfaces(this.getTarget().getClass()), this);
}
/** * 实现InvocationHandler的接口方法,将具体的调用委托给拦截器链MethodInterceptorChain */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MyMethodInterceptor[] iterceptors =
AdvisorHelper.getMethodInterceptors(this.getAdvisors(), method);
Object obj = new MethodInterceptorChain(iterceptors)
.intercept(method,args,proxy);
return obj;
}
}
复制代码
CGLIB是经过回调(Callback)实现的,须要实现CGLIB的MethodInterceptor
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxyImpl extends AOPProxy {
public CglibProxyImpl(List<Advisor> advisors, Object bean) {
super(advisors, bean);
}
@Override
protected Object getProxyObject() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.getTarget().getClass());
enhancer.setCallback(new AOPInterceptor());
return enhancer.create();
}
/** * 实现cglib的拦截器,在intercept中将拦截器调用委托给拦截器链MethodInterceptorChain */
private class AOPInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
MyMethodInterceptor[] iterceptors = AdvisorHelper.getMethodInterceptors(CglibProxyImpl.this.getAdvisors(), method);
Object o = new MethodInterceptorChain(iterceptors)
.intercept(method, args, obj);
return o;
}
}
}
复制代码
以上,基本上实现了建立代理对象的流程,那么咱们思考一个问题
在调用代理方法的时候,是如何实现调用咱们定义的Advice的呢?
咱们先用一种简单的实现方式说明一下,以JDK代理方式为例:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return obj;
}
复制代码
咱们知道,执行代理对象的任何方法都会进入到invoke里(对动态代理还不清楚的同窗能够回看第三章动态代理的实现),那么进入到invoke里面以后咱们须要作以下判断:
咱们以BeforeAdvice为例,展现一下如何实现Advice调用
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
BeforeAdvice beforeAdvice = getBeforeAdvice(method);
beforeAdvice.before(proxy, method, args);//调用Advice处
return method.invoke(this.bean, args);
}
/** * 以返回BeforeAdvice为例 * @return */
private BeforeAdvice getBeforeAdvice(Method method) {
for (Advisor advisor : this.getAdvisors()) {
if(AdvisorHelper.isMatch(advisor, method)
&& advisor.getAdvice() instanceof BeforeAdvice) {
return (BeforeAdvice) advisor.getAdvice();
}
}
return null;
}
复制代码
那么,问题来了,若是咱们获取到匹配的Advice中还有AfterAdvice呢?咱们向invoke方法中增长代码
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
BeforeAdvice beforeAdvice = getBeforeAdvice(method);
beforeAdvice.before(proxy, method, args);//调用Advice处
Object o = method.invoke(this.bean, args);
AfterAdvice afterAdvice = getAfterAdvice(method);
afterAdvice.after(proxy, method, args);//调用Advice处
return o;
}
复制代码
那么,若是咱们得到到两个或者多个相同类型的Advice呢?而且相同类型的Advice间有执行顺序需求。上面这种简单实现就没法知足了,咱们须要引入方法拦截器链
这里作一个简单的扩展,不少拦截器(interceptor),过滤器(filter)的实现都是基于职责链模式实现的,在定义方法拦截器链以前,咱们先看看Tomcat是如何实现过滤器(filter)的。
注:确切来讲是,Tomcat基于JavaEE标准实现的
Java Sevlet接口
public interface FilterChain {
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException;
}
public interface Filter {
public void init(FilterConfig filterConfig) throws ServletException;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
public void destroy();
}
复制代码
Tomcat过滤器链实现
public final class ApplicationFilterChain implements FilterChain {
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
void addFilter(ApplicationFilterConfig filterConfig) {
//..
}
@Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
// Call the next filter if there is one
//C-1
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = filterConfig.getFilter();
filter.doFilter(request, response, this);
return;
}
// We fell off the end of the chain -- call the servlet instance
servlet.service(request, response);
}
}
复制代码
Session初始化过滤器
public class SessionInitializerFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
((HttpServletRequest)request).getSession();
//C-2
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// NO-OP
}
@Override
public void destroy() {
// NO-OP
}
}
复制代码
以上实现有几个关键点:
咱们引入职责链模式,将Advice抽象成一个MethodInterceptor。这对功能实现上有以下好处:
定义拦截器,为了和CGLIB的拦截器区分开,咱们命名为MyMethodInterceptor
public interface MyMethodInterceptor {
public Object intercept(Method method, Object[] arguments, Object target, MethodInterceptorChain chain);
}
复制代码
定义BeforeAdvice和AfterAdvice
public class BeforeAdvice extends Advice implements MyMethodInterceptor {
public BeforeAdvice(Method adviceMethod, Aspect aspect) {
super(adviceMethod, aspect);
}
public void before(final Object target, final Method method, final Object[] args) {
this.invokeAspectMethod(target, method, args);
;
}
@Override
public Object intercept(Method method, Object[] arguments, Object target, MethodInterceptorChain chain) {
this.before(target, method, arguments);
return chain.intercept(method, arguments, target);
}
}
public class AfterAdvice extends Advice implements MyMethodInterceptor {
public AfterAdvice(Method adviceMethod, Aspect aspect) {
super(adviceMethod, aspect);
}
public void after(final Object target, final Method method, final Object[] args) {
this.invokeAspectMethod(target, method, args);
}
@Override
public Object intercept(Method method, Object[] arguments, Object target, MethodInterceptorChain chain) {
Object obj = chain.intercept(method, arguments, target);
this.after(target, method, arguments);
return obj;
}
}
复制代码
实现方法拦截器链
public class MethodInterceptorChain {
private MyMethodInterceptor[] methodInterceptors;
public MethodInterceptorChain(MyMethodInterceptor[] methodInterceptors) {
this.methodInterceptors = methodInterceptors;
}
private int index = 0;
public Object intercept(Method method, Object[] arguments, Object target) {
if (index == methodInterceptors.length) {
// call method
return method.invoke(target, arguments);
} else {
return methodInterceptors[index++]
.intercept(method, arguments, target, this);
}
return null;
}
}
复制代码
那么回到咱们最开始的思考题,咱们能够把本来简单的实现替换成MethodInterceptorChain,以下:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MyMethodInterceptor[] iterceptors =
AdvisorHelper.getMethodInterceptors(this.getAdvisors(), method);
Object obj = new MethodInterceptorChain(iterceptors)
.intercept(method,args,proxy);
return obj;
}
复制代码
这样,咱们就将代理方法的调用转移到了MethodInterceptorChain
最后,这里面还隐藏一个小问题,就是代理对象中的Advisor是全部和这个类相关的,咱们仍然须要根据method和pointcut找到与方法相匹配的拦截器,这和前面筛选Advisor的实现是同样的,都是基于AspectJ具
在讲完方法拦截器链以后,代理调用的流程也就清晰了,也就再也不赘述。
咱们本次实现仅仅是基于AspectJ的Annotation配置,Spring AOP同时也支持基于Schema配置。时间与篇幅缘由,就再也不作深刻探讨。
除了本文重点提到的职责链模式,Spring AOP还运用了大量的工厂模式、模板方法模式、适配器模式等。特别是大量使用工厂(好比Aspect工厂,Advisor工厂等)同时配合Spring IoC的状况下,可以支持类和对象(Aspect、Advisor等)强大的管理,包括了加载策略,好比单例,多例,懒加载等。笔者认为,这些值得你们深刻学习和研究的。