Spring

Spring | 0.9 AOP

2020-05-12  本文已影响0人  不一样的卡梅利多

AOP

核心功能:将业务代码与非业务代码连接到一起,并且还需要集成到bean 容器中

核心类视图

AOP 核心类.png

AOP 与beans 集成

spring 创建ProxyFactoryBean 调用时序
1. spring读取配置 ,实例化ProxyFactoryBean,并且设置setProxyInterfaces(String[] interfaceNames)

  1. ProxyFactoryBean 创建完成后,调用setBeanFactory(BeanFactory beanFactory),afterPropertiesSet()

  2. 由于ProxyFactoryBean 是一个FactoryBean ,还需要依据继续创建对象 FactoryBean.getObject()

FactoryBean.getObject 实现

public Object getObject() throws BeansException {
        if (this.singleton) {
            // Return singleton
            return this.singletonInstance;
        }
        else {
            // Create new interface
            return createInstance();
        }
    }
private Object createInstance() {
        refreshInterceptorChain();
        AopProxy proxy = new AopProxy(this);
        return AopProxy.getProxy(getClass().getClassLoader(), proxy);
    }

refreshInterceptorChain: 实例化 MethodPointcut bean,并且创建InvokerInterceptor

AopProxy.getProxy:依据配置创建动态代理对象。生成的代理对象调方法调用逻辑走AopProxy.invoke 方法,委派给MethodInvocationImpl 实现,对方法调用添加配置的一系列拦截器。实现了代码动态链接功能。

    public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
        // Create a new invocation object
        // TODO refactor into InvocationFactory?
        MethodInvocationImpl invocation = new MethodInvocationImpl(proxy, config.getTarget(), 
                                    method.getDeclaringClass(), //?
                                    method, args,
                                    this.config.getMethodPointcuts(), // could customize here
                                    this.config.getAttributeRegistry());
        
        if (this.config.getExposeInvocation()) {
            // Make invocation available if necessary
            AopContext.setCurrentInvocation(invocation);
        }
        
        try {
            if (EQUALS_METHOD.equals(invocation.getMethod())) {
                // What if equals throws exception!?
                logger.debug("Intercepting equals() method in proxy");
                return invocation.getMethod().invoke(this, invocation.getArguments());
            }
            
            Object retVal = invocation.invokeNext();
            if (retVal != null && retVal == invocation.getInvokedObject()) {
                // Special case: it returned this
                // Note that we can't help if the target sets
                // a reference to itself in another returned object
                logger.debug("Replacing 'this' with reference to proxy");
                retVal = proxy;
            }
            return retVal;
        }
        finally {
            if (this.config.getExposeInvocation()) {
                AopContext.setCurrentInvocation(null);
            }
        
            //if (logger.isDebugEnabled()) {
            //  logger.debug("Processed invocation [" + invocation + "]");
            //}
        }
    }

Spring 专题

上一篇下一篇

猜你喜欢

热点阅读