spring(四) aop

aop自定义配置

aop利用了spring的自定义标签

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

在bean的配置文件中只要找到了aop命名空间对应的标签,就会通过AopNamespaceHandler进行解析。

    @Override
	public void init() {
		// In 2.0 XSD as well as in 2.5+ XSDs
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace in 2.5+
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

aop注册beanPostProcessor

重点来分析一下AspectJAutoProxyBeanDefinitionParser

    public BeanDefinition parse(Element element, ParserContext parserContext) {
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		extendBeanDefinition(element, parserContext);
		return null;
	}
    // 主要是注册了这个AnnotationAwareAspectJAutoProxyCreator bean定义
    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

AnnotationAwareAspectJAutoProxyCreator这个类实现了InstantiationAwareBeanPostProcessor这个接口。按照前文描述的扩展点来说会在bean的实例化周期按照次序调用其具体的方法。主要关注一下postProcessAfterInitialization。 aop就是利用了这个方法,在获取到原对象之后对其进行增强。

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

简短总结:

aop生效的原理

        配置了aop,就会让其注册AnnotationAwareAspectJAutoProxyCreator这个bean定义,其本质利用了spring的扩展点,让每一个bean初始化之后都会调用postProcessAfterInitialization方法,从而返回生成的新的代理对象

aop的postProcess方法

在上述描述中已经知道为什么aop会生效了,其postProcessAfterInitialization方法也就是生成代理的方法,其实生成代理的方法也很好描述,就是找到哪个对象需要代理,代理之后的方法如何实现。

aop中三个概念

Advice

Advice 就是你想要添加到现有代码中的额外逻辑。

Pointcut

决定了“哪里”应用 Advice

Advisor

可以看作是一个将 Advice 与 Pointcut 结合起来的概念

找到advisor

// 找到合适的advisor的外层方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		// 找到所有的advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 找到当前bean对应的advisor
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
// 找到所有的advisor
    protected List<Advisor> findCandidateAdvisors() {
		// 找到实现了advisor接口的对象
		List<Advisor> advisors = super.findCandidateAdvisors();
		// 找到所有被aspect标记的对象
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		return advisors;
	}
// 找到注册到bean工厂定义的所有Advisor
public List<Advisor> findAdvisorBeans() {
    String[] advisorNames = this.cachedAdvisorBeanNames;
    advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
    for (String name : advisorNames) {
        List<Advisor> advisors = new ArrayList<Advisor>();
        advisors.add(this.beanFactory.getBean(name, Advisor.class));
    }
    
}
// 这个是pointcutAdvisor类型的根据当前类匹配advisor的方法
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

代理增强

代理增强有两种方案

一种是基于接口的jdk动态代理、而是基于当前类为父类的cglib动态代理。默认是jdk动态代理,但是如果在aop配置中指定了traget-class,则会默认使用cglib

入口:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

// 生成动态代理工厂,然后去获取代理类
protected Object createProxy(
			Class<?> beanClass, String beanName, 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);
		return proxyFactory.getProxy(getProxyClassLoader());
	}

接下来以jdk动态代理为例,看看其是怎么生成代理的,jdk动态代理主要是要实现InvocationHandler接口,然后在调用方法的时候会调用到其invoke方法

public Object getProxy(ClassLoader classLoader) {
        // 找到合适的代理的父接口,然后生成代理
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
    @Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		    // 构建切面的拦截器链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
		// 通过构造的拦截器链进行方法调用
		retVal = invocation.proceed();
		
	}

通过切面构造拦截器链的过程。主要两种方式

1、通过注册到AdvisorAdapterRegistry

2、advisor本身实现了MethodInterceptor接口

AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);


public MethodInterceptor[] getInterceptors(Advisor advisor) {
		List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
		Advice advice = advisor.getAdvice();
        // 自身实现了MethodInterceptor接口
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}
        // 通过注册上来的适配器,转换成对应的interceptor
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
	}

// 默认注册上来的interceptor
public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}

链式调用interceptor方法

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();

public Object proceed() throws Throwable {
        // 调用链执行完了之后,执行被代理对象的方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
        // 获取下一个执行的拦截器
		Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        // 执行下一个拦截器的invoke方法
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值