zoukankan      html  css  js  c++  java
  • Spring AOP源码解析

    AOP源码分析

    gradle引入aop的依赖:

    group 'org.springframework'
    version '5.1.21.BUILD-SNAPSHOT'
    
    apply plugin: 'java'
    
    sourceCompatibility = 1.8
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile(project(":spring-context"))
        compile group:'org.aspectj',name:'aspectjweaver',version: '1.8.6'
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }
    
    

    我们知道AOP的实现是使用的动态代理的方式,那必然是在创建对象的时候创建了一个代理对象。

    那么代理类是什么时候创建的呢?实际上代理类的创建是通过BeanPostProcessor的后置处理来做的。

    经过之前IOC源码的学习,我们可以知道,后置处理器的代码的位置。

    @Override
    	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    			throws BeansException {
    
    		Object result = existingBean;
    		for (BeanPostProcessor processor : getBeanPostProcessors()) {
    			Object current = processor.postProcessAfterInitialization(result, beanName);
    			if (current == null) {
    				return result;
    			}
    			result = current;
    		}
    		return result;
    	}
    

    它会遍历所有实现了BeanPostProcessor的Bean,其中有一个AspectJAwareAdvisorAutoProxyCreator,看名字就知道跟AOP是相关的。既然它实现了BeanPostProcessor接口,我们就要去找它的postProcessAfterInitialization
    方法。

    当前类没有,就往父类里面找,在AbstractAutoProxyCreator里面找到

    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    		if (bean != null) {
    			Object cacheKey = getCacheKey(bean.getClass(), beanName);
    			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    				return wrapIfNecessary(bean, beanName, cacheKey);
    			}
    		}
    		return bean;
    	}
    

    跟踪wrapIfNecessary方法进入

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    			return bean;
    		}
    		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    			return bean;
    		}
    		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    			this.advisedBeans.put(cacheKey, Boolean.FALSE);
    			return bean;
    		}
    
    		// 如果有设置增强的话,就创建代理对象
    		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    		if (specificInterceptors != DO_NOT_PROXY) {
    			this.advisedBeans.put(cacheKey, Boolean.TRUE);
    			Object proxy = createProxy(
    					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    			this.proxyTypes.put(cacheKey, proxy.getClass());
    			return proxy;
    		}
    
    		this.advisedBeans.put(cacheKey, Boolean.FALSE);
    		return bean;
    	}
    

    可以看出如果有设置aop相关增强的话,就会去调用createProxy方法,创建并返回代理对象。

    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
    			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
    
    		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
    			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
    		}
    
    		ProxyFactory proxyFactory = new ProxyFactory();
    		proxyFactory.copyFrom(this);
    
    		if (!proxyFactory.isProxyTargetClass()) {
    			if (shouldProxyTargetClass(beanClass, beanName)) {
    				proxyFactory.setProxyTargetClass(true);
    			}
    			else {
    				evaluateProxyInterfaces(beanClass, proxyFactory);
    			}
    		}
    
    		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    		proxyFactory.addAdvisors(advisors);
    		proxyFactory.setTargetSource(targetSource);
    		customizeProxyFactory(proxyFactory);
    
    		proxyFactory.setFrozen(this.freezeProxy);
    		if (advisorsPreFiltered()) {
    			proxyFactory.setPreFiltered(true);
    		}
    
    		return proxyFactory.getProxy(getProxyClassLoader());
    	}
    

    我们点proxyFactory.getProxy这个方法,发现他有两个实现。

    接下来就会根据这两个不同的实现创建出代理对象,对原方法进行增强。

    书山有路勤为径,学海无涯苦作舟
  • 相关阅读:
    TMD 这个写笔记的号,盗了有意思吗
    类成员的指针必须NULL化,否则是乱七八糟的东西
    超前引用不可使用类名来定义变量和函数的变量参数,只可用来定义引用或者指针。
    XP下,移动窗口产生重影的问题
    生成ico格式图标
    设置窗口的z-order总是在最底部
    关于windows的锁定状态
    使用Layered Window遇到的一些问题及解决方法
    转-使用wifi调试程序
    URL的格式
  • 原文地址:https://www.cnblogs.com/javammc/p/15582395.html
Copyright © 2011-2022 走看看