转载自:https://blog.csdn.net/moreevan/article/details/11977115/
https://blog.csdn.net/qq_38182963/article/details/78747404
https://blog.csdn.net/xiaoxufox/article/details/54695200
https://mp.weixin.qq.com/s?__biz=MzAxNjk4ODE4OQ==&mid=2247484741&idx=1&sn=42310e59d06abc3fa08454949e3a17aa&chksm=9bed2437ac9aad21cb5e635bef607e1c0631ea9e8ca88fed8f65ecb61ca69f1951679d84ee41&scene=21#wechat_redirect
AOP(Aspect-Oriented Programming)面向切面的编程,在平时的开发过程中,AOP其实用到的地方一般有:
①用来做日记的处理
②方法的调用统计
③业务层面的读写分离(例如自定义的Annotation+AOP可以实现切换数据源)
④自定义权限拦截器
在Spring框架中,AOP则发挥了不少功效,例如spring的事务。
AOP具体的介绍移步:https://blog.csdn.net/zero__007/article/details/46765191
在介绍代码之前先介绍Spring Aop中一些核心类,大致分为三类:
• advisor:顾问的意思,advisor是Spring中切面的体现形式,封装了spring aop中的切点和通知。包括有:
DefaultPointcutAdvisor
: 默认切面顾问,比较灵活。可自由组合切面和通知。
InstantiationModelAwarePointcutAdvisorImpl
: springboot自动装配的顾问类型,也是最常用的一种顾问实现。在注解实现的切面中,所有@Aspect注释的类,都会被解析成该对象。
…
• advice:通知,也就是 Spring AOP 中增强的方法。包括有:
AspectJMethodBeforeAdvice
:前置通知,AspectJ中 before 属性对应的通知(@Before标注的方法会被解析成该通知),在切面方法执行之前执行。
AspectJAfterReturningAdvice
:后置通知,AspectJ中 afterReturning 属性对应的通知(@AfterReturning 标注的方法会被解析成该通知),在切面方法执行之后执行,如果有异常,则不执行。注意:该通知与AspectJMethodBeforeAdvice对应。
AspectJAroundAdvice
:环绕通知,AspectJ中 around 属性对应的通知(@Around标注的方法会被解析成该通知),在切面方法执行前后执行。
AspectJAfterAdvice
:返回通知,AspectJ中 after 属性对应的通知(@After 标注的方法会被解析成该通知),不论是否异常都会执行。
• advisorCreator:代理机制,抽象类AbstractAutoProxyCreator的每个实现类代表着一种代理机制。默认情况下只使用一种代理机制。 继承 spring ioc的扩展接口 beanPostProcessor,主要用来扫描获取 advisor。包括有:
AbstractAutoProxyCreator
:代理机制抽象类,Spring 为Spring AOP 模块暴露的扩展类,也是 AOP 中最核心的类。Nepxion Matrix 框架便是基于此类对AOP进行扩展和增强。
AspectJAwareAdvisorAutoProxyCreator
:Aspectj的实现方式,也是Spring Aop中最常用的实现方式,如果用注解方式,则用其子类AnnotationAwareAspectJAutoProxyCreator。
AnnotationAwareAspectJAutoProxyCreator
:目前最常用的AOP使用方式。spring aop 开启注解方式之后,该类会扫描所有@Aspect()标准的类,生成对应的adviosr。目前SpringBoot框架中默认支持的方式,自动配置。
在Spring中,使用AOP需要在xml中添加 Aop:config
或 Aop:aspectj-autoproxy
标签。Spring会使用AopNamespaceHandler#init
注册这类标签解析器beanDefinitionparser:
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
AspectJAutoProxyBeanDefinitionParser
和ConfigBeanDefinitionParser
都是BeanDefinitionParser的子类。
在解析为BeanDefinition时,BeanDefinitionParserDelegate#parseCustomElement
会调用到这个BeanDefinitionParser的parse方法:
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = this.getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
} else {
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
}
来关注看下AspectJAutoProxyBeanDefinitionParser
:
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
//解析aspectj-autoproxy标签
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
//解析子标签
extendBeanDefinition(element, parserContext);
return null;
}
// …
}
AopNamespaceUtils类:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册bean:AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//设置proxy-target-class和expose-proxy这两个属性
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册到ParserContext
registerComponentIfNecessary(beanDefinition, parserContext);
}
下面是关键类AnnotationAwareAspectJAutoProxyCreator
:
AnnotationAwareAspectJAutoProxyCreator
继承了SmartInstantiationAwareBeanPostProcessor
。AbstractAutoProxyCreator
中对SmartInstantiationAwareBeanPostProcessor
的接口有实现:
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
// ...
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
//advisedBeans用于存储不可代理的bean,如果包含直接返回
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//isInfrastructureClass判断是否是Advisor、Advice、AopInfrastructureBean,如果是,则不能被代理
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//到这里说明该bean可以被代理,所以去获取自定义目标类,如果没有定义,则跳过。
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
//获取bean适配的Advice
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
//创建代理
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
//如果最终可以获得代理类,则返回代理类,直接执行实例化后置通知方法
return proxy;
}
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
//…
}
在bean实例化前和后会调用SmartInstantiationAwareBeanPostProcessor接口方法,看代码注释就大致知道是什么过程。来看 shouldSkip
方法,shouldSkip会跳过切面类,怎么判定呢?在子类AspectJAwareAdvisorAutoProxyCreator中:
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
通过findCandidateAdvisors()
方法来获取所有的候选 advisor:
@Override
protected List<Advisor> findCandidateAdvisors() {
//获得 Advisor 实现类
List<Advisor> advisors = super.findCandidateAdvisors();
// 处理@Aspect注解类, 解析成Advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
buildAspectJAdvisors()
方法会解析@Aspect注解类,将该类所有被@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut注解的方法封装成advisor。
可以看出来,创建advisor的逻辑发生在扩展接口中的postProcessBeforeInstantiation
,实例化之前执行,如果有自定义的TargetSource指定类,则直接生成代理类,这种情况使用不多,常规代理类还是在postProcessAfterInitialization
中创建,也就是 IOC 最后一个扩展方法。
在bean实例化之后,调用postProcessAfterInitialization()
来生成代理类,来看下里面的wrapIfNecessary()
方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && 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;
}
//获取适合的advise
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;
}
先获取到合适的advisor,如果不为空,则调用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);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}