zoukankan      html  css  js  c++  java
  • Spring Aop源码分析

    最近看了SpringAop的源码实现  大概记录一下aop的源码流程

    创建一个最简单的一个测试类

    package com.zcg.learn.Test;

    import org.aopalliance.aop.Advice;
    import org.junit.Test;
    import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
    import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
    import org.springframework.aop.framework.Advised;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.tests.aop.advice.CountingAfterReturningAdvice;
    import org.springframework.tests.aop.advice.CountingBeforeAdvice;

    import com.zcg.learn.UserService;
    import com.zcg.learn.UserServiceImpl;

    /**
    * SpringAop源码分析测试类
    * @author zcg
    * 2018/3/1
    *
    */
    public class SpringAopTest {

    /**
    * 创建代理
    */
    @Test
    public void createProxyTest() {
    Object target = new UserServiceImpl();
    ProxyFactory pf = new ProxyFactory(target);
    //CountingBeforeAdvice 前置通知计数器
    CountingBeforeAdvice countingBeforeAdvice = new CountingBeforeAdvice();
    pf.addAdvice(countingBeforeAdvice);
    UserService service = (UserService) pf.getProxy();
    service.addUser();
    }

    /**
    * 动态添加 移除通知
    */
    @Test
    public void createProxyTest2() {
    Object target = new UserServiceImpl();
    ProxyFactory pf = new ProxyFactory(target);
    UserService service = (UserService) pf.getProxy();
    Advised advised = (Advised) service;
    CountingBeforeAdvice countingBeforeAdvice = new CountingBeforeAdvice();
    CountingAfterReturningAdvice countingAfterReturningAdvice = new CountingAfterReturningAdvice();
    advised.addAdvice(countingAfterReturningAdvice);
    advised.addAdvice(countingBeforeAdvice);
    service.addUser();
    advised.removeAdvice(countingAfterReturningAdvice);
    service.addUser();
    }

    @Test
    public void createProxyAspectJByTest() {
    Object target = new UserServiceImpl();
    AspectJProxyFactory pf = new AspectJProxyFactory(target);
    AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
    advisor.setExpression("execution(* *.addUser(..))");
    CountingBeforeAdvice counting = new CountingBeforeAdvice();
    advisor.setAdvice(counting);
    pf.addAdvisor(advisor);
    UserService userService = pf.getProxy();
    userService.addUser();
    /**
    * advice 通知拦截器
    * advisor 通知加切入点适配器
    */


    }

    }

    其中测试方式

    @Test
    public void createProxyTest() {
    Object target = new UserServiceImpl();


    ProxyFactory pf = new ProxyFactory(target);
    //CountingBeforeAdvice 前置通知计数器
    CountingBeforeAdvice countingBeforeAdvice = new CountingBeforeAdvice();
    pf.addAdvice(countingBeforeAdvice);
    UserService service = (UserService) pf.getProxy();
    service.addUser();
    }

    1.target 以构造参数的形式放入在ProxyFactory中,实际上将该tartget放入在AdvisedSupport类中

    2.countingBeforeAdvice 为Spring Aop自带的前置通知计数

    3.1 UserService service = (UserService) pf.getProxy();从中获取代理类

    ProxyFactory类中 extends ProxyCreatorSupport

    /*

    * 代理生成工厂
    */
    @SuppressWarnings("serial")
    public class ProxyFactory extends ProxyCreatorSupport {

    /**
    * Create a new proxy according to the settings in this factory.
    * <p>Can be called repeatedly. Effect will vary if we've added
    * or removed interfaces. Can add and remove interceptors.
    * <p>Uses a default class loader: Usually, the thread context class loader
    * (if necessary for proxy creation).
    * @return the proxy object
    */
    public Object getProxy() {
    return createAopProxy().getProxy();
    }

    }

    3.2 createAopProxy()方法是父类ProxyCreatorSupport里面的方法 

    protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
    activate();
    }

    //得到Aop代理工厂和在当前代理工厂创建该代理类
    return getAopProxyFactory().createAopProxy(this);
    }

    其中getAopProxyFactory().createAopProxy(this)在DefaultAopProxyFa1ctory类中执行 具体代码如下

    @SuppressWarnings("serial")
    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

    @Override
    public 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.");
    }

    //r如果目标类有接口或者是代理类,则走jdk的动态代理 否则走cglib的动态代理
    if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    return new JdkDynamicAopProxy(config);
    }
    return new ObjenesisCglibAopProxy(config);
    }
    else {
    return new JdkDynamicAopProxy(config);
    }
    }

    /**
    * Determine whether the supplied {@link AdvisedSupport} has only the
    * {@link org.springframework.aop.SpringProxy} interface specified
    * (or no proxy interfaces specified at all).
    */
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
    Class<?>[] ifcs = config.getProxiedInterfaces();
    return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
    }

    }

    3.3 JdkDynamicAopProxy类实现了InvocationHandler 对invoke进行的重写 核心代码如下

    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

    @Override
    public 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;

    try {
    if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
    // The target does not implement the equals(Object) method itself.
    return equals(args[0]);
    }
    else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
    // The target does not implement the hashCode() method itself.
    return hashCode();
    }
    else if (method.getDeclaringClass() == DecoratingProxy.class) {
    // There is only getDecoratedClass() declared -> dispatch to proxy config.
    return AopProxyUtils.ultimateTargetClass(this.advised);
    }
    else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
    // Service invocations on ProxyConfig with the proxy config...
    return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
    }

    Object retVal;

    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.
    target = targetSource.getTarget();
    if (target != null) {
    targetClass = target.getClass();
    }

    // Get the interception chain for this method. 生成通知链条 当前对象和方式是否在拦截范围内
    List<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()) {
    // 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...  

    //初始化MethodInvocation类
    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    // Proceed to the joinpoint through the interceptor chain.

    执行调用链的所有方法和本身方法
    retVal = invocation.proceed();
    }

    // Massage return value if necessary.
    Class<?> returnType = method.getReturnType();
    if (retVal != null && retVal == target &&
    returnType != Object.class && 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);
    }
    }
    }

    }

    其中的 AdvisedSupport类的this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)方法主要得到代理的所有拦截器方法

    核心代码如下

    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
    MethodCacheKey cacheKey = new MethodCacheKey(method);
    List<Object> cached = this.methodCache.get(cacheKey);
    if (cached == null) {
    cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
    this, method, targetClass);
    this.methodCache.put(cacheKey, cached);
    }
    return cached;
    }

    getInterceptorsAndDynamicInterceptionAdvice方法核心代码如下:

    public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

    @Override
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
    Advised config, Method method, Class<?> targetClass) {

    // This is somewhat tricky... We have to process introductions first,
    // but we need to preserve order in the ultimate list.
    List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    for (Advisor advisor : config.getAdvisors()) {
    if (advisor instanceof PointcutAdvisor) {
    // Add it conditionally.
    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
    if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
    if (mm.isRuntime()) {
    // Creating a new object instance in the getInterceptors() method
    // isn't a problem as we normally cache created chains.
    for (MethodInterceptor interceptor : interceptors) {
    interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
    }
    }
    else {
    interceptorList.addAll(Arrays.asList(interceptors));
    }
    }
    }
    }
    else if (advisor instanceof IntroductionAdvisor) {
    IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
    if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
    Interceptor[] interceptors = registry.getInterceptors(advisor);
    interceptorList.addAll(Arrays.asList(interceptors));
    }
    }
    else {
    Interceptor[] interceptors = registry.getInterceptors(advisor);
    interceptorList.addAll(Arrays.asList(interceptors));
    }
    }

    return interceptorList;
    }

    }

    3.4 invocation.proceed()核心代码如下

    public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable{

    @Override
    public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    return invokeJoinpoint();
    }

    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.
    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
    }

    }

    其中前置拦截器方法如下

    @SuppressWarnings("serial")
    public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

    private MethodBeforeAdvice advice;


    /**
    * Create a new MethodBeforeAdviceInterceptor for the given advice.
    * @param advice the MethodBeforeAdvice to wrap
    */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
    Assert.notNull(advice, "Advice must not be null");
    this.advice = advice;
    }

    //重写invoke方法

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
    return mi.proceed();
    }

    }

    后置通知拦截器方法

    @SuppressWarnings("serial")
    public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

    private final AfterReturningAdvice advice;


    /**
    * Create a new AfterReturningAdviceInterceptor for the given advice.
    * @param advice the AfterReturningAdvice to wrap
    */
    public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
    Assert.notNull(advice, "Advice must not be null");
    this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
    Object retVal = mi.proceed();
    this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
    return retVal;
    }

    }

    流程大概如此  可能有点模糊,如果想继续学习加我QQ:1051980588 一起探讨和看其他相关的源码解析视频  

  • 相关阅读:
    FastDFS+Nginx部署详细教程
    简单的区别记录
    linux搜索命令之find和grep
    [转载]redis持久化的两种操作RDB和AOF
    多线程的一点点整理
    利用spring-mail模块发送带附件邮件dome
    java集合类总结
    微信支付 遇到的问题
    dubbo监控工具
    Maven配置dubbo环境简单例子
  • 原文地址:https://www.cnblogs.com/zcg1051980588/p/10469697.html
Copyright © 2011-2022 走看看