通知接收器(advisor)
拦截器(advise)
匹配器(pointcut)
《aop命名空间》:
spring-aop-4.3.6.RELEASE.jar、spring-aspects-4.3.6.RELEASE.jar
hook机制是:
aop的“命名空间的指定标签处理器”在处理指定标签的时候,会自动注册bean级别的hook - org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator
aop的配置 - 使用xml配置
<aop:scoped-proxy proxy-target-class="true" /> BeanDefinition装饰器机制 - 劫持 BeanDefinition 的信息,以CGLIB生成子类
<aop:config>
aop的配置 - 使用注解配置
<aop:include name="aspect4AspectJAutoProxyTag[0-9]" /> 正则表达式,用来匹配通知者接收者的beanName
当通知接收者的Aspect的value有配置值时,bean的必须scope="prototype"
@Aspect(...)、@Before(...)、@After(...)、@Around(...)、@AfterReturning(...)、@AfterThrowing(...)
org.springframework.aop.config.internalAutoProxyCreator注册的优先级
注册 XxxAspectJAwareAdvisorAutoProxyCreator的时候有个优先级关系
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
<aop:config>
// <aop:config> 居于xml的解析
org.springframework.aop.config.ConfigBeanDefinitionParser.parse
{
1、如果没有,注册AspectJAwareAdvisorAutoProxyCreator到beanFactory,《beanName为org.springframework.aop.config.internalAutoProxyCreator》
如果有设置 proxy-target-class="",那么设置AspectJAwareAdvisorAutoProxyCreator的属性
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
如果有设置 expose-proxy="",那么设置AspectJAwareAdvisorAutoProxyCreator的属性
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
2、注册子元素
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts)
{
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
// <aop:pointcut id="aspectJExpressionPointcut01" expression="execution(* cn.java.demo.aoptag.bean.HelloServiceImpl4ConfigAopWithAdvisorTag.method1(..))" />
// parsePointcut(elt, parserContext); 匹配规则的定义
1、注册AspectJExpressionPointcut到beanFactory
}
else if (ADVISOR.equals(localName)) {
// <aop:advisor id="aspectJPointcutAdvisor00" pointcut-ref="aspectJExpressionPointcut01" advice-ref="aspectJMethodBeforeAdviceMock" order="1" />
// parseAdvisor(elt, parserContext); 定义《匹配规则和切入点处理器的关系》
2、注册DefaultBeanFactoryPointcutAdvisor到beanFactory
}
else if (ASPECT.equals(localName)) {
// <aop:aspect id="aspectId_12_aspectMethodAround" ref="aspect4AopConfigAllTag12" order="1"> <!-- 以Poxy的方式实现AOP,不会用CGLIB生成子类 -->
// <aop:pointcut id="pointcutRefId_12_aspectMethodAround" expression="execution(public String cn.java.demo.aoptag.bean.HelloServiceImpl4ConfigAopWithAdvisorTag1.method3(..))" />
// <aop:around method="aspectMethodAround" pointcut-ref="pointcutRefId_12_aspectMethodAround" />
// </aop:aspect>
// parseAspect(elt, parserContext); // 定义《匹配规则和切入点处理器方法的关系》
1、注册AspectJPointcutAdvisor到beanFactory (存放《表达式beanName和报关接收器的关系》)
2、注册AspectJExpressionPointcut到beanFactory(表达式bean)
}
}
}
// Processor
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator
{
1、实例化前
postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
{
}
2、初始化后
postProcessAfterInitialization(Object bean, String beanName)
{
return wrapIfNecessary(bean, beanName, cacheKey);
{
1、过滤不能被代理的
1、 -- 实现Advice/Pointcut/Advisor/AopInfrastructureBean接口的类不能被代理
2、 -- 要创建的是“接受通知的对象”,那么就要跳过了,不然陷入死循环
2、获取符合条件的“通知接受者”列表 --- getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)
findEligibleAdvisors(Class<?> beanClass, String beanName)
{
1、扫描所有“通知接受者”列表 - 扫描bean容器,找出实现Advisor接口的bean列表 --- findCandidateAdvisors()
2、匹配“通知接受者”列表 --- findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)
1、ClassFilter匹配
2、MethodMatcher匹配 - 《类中只要有一个方法能命中,就符合》
3、对结果进行排序 --- sortAdvisors(eligibleAdvisors)
}
3、创建代理对象 - 返回
1、配置优化模式
new ObjenesisCglibAopProxy(config);
2、没配置优化模式
new JdkDynamicAopProxy(config)
}
}
}
<aop:aspectj-autoproxy> 居于注解的解析
// <aop:aspectj-autoproxy> 居于注解的解析
{
1、如果没有,注册AnnotationAwareAspectJAutoProxyCreator到beanFactory,《beanName为org.springframework.aop.config.internalAutoProxyCreator》
如果有设置 proxy-target-class="",那么设置AnnotationAwareAspectJAutoProxyCreator的属性
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
如果有设置 expose-proxy="",那么设置AnnotationAwareAspectJAutoProxyCreator的属性
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
2、设置AnnotationAwareAspectJAutoProxyCreator的属性
beanDef.getPropertyValues().add("includePatterns", includePatterns);
}
// Processor
org.springframework.aop.aspectj.autoproxy.AnnotationAwareAspectJAutoProxyCreator
{
1、实例化前
postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
{
}
2、初始化后
postProcessAfterInitialization(Object bean, String beanName)
{
return wrapIfNecessary(bean, beanName, cacheKey);
{
1、过滤不能被代理的
1、 -- 实现Advice/Pointcut/Advisor/AopInfrastructureBean接口的类不能被代理
2、 -- 要创建的是“接受通知的对象”,那么就要跳过了,不然陷入死循环
2、获取符合条件的“通知接受者”列表 --- getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)
findEligibleAdvisors(Class<?> beanClass, String beanName)
{
1、findCandidateAdvisors()
{
1、扫描所有“通知接受者”列表 - 扫描bean容器,找出实现Advisor接口的bean列表
2、居于注解扫描
for(迭代所有bean){
1、beanName 符合特征 includePatterns
2、反射包含@Aspect注解的类里面的所有方法,在方法上查找注解,用InstantiationModelAwarePointcutAdvisorImpl包装方法,获取Advisor列表
}
}
2、匹配“通知接受者”列表 --- findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName)
1、ClassFilter匹配
2、MethodMatcher匹配 - 《类中只要有一个方法能命中,就符合》
3、对结果进行排序 --- sortAdvisors(eligibleAdvisors)
}
3、创建代理对象 - 返回
1、配置优化模式
new ObjenesisCglibAopProxy(config);
2、没配置优化模式
new JdkDynamicAopProxy(config)
}
}
}
代理机制(切面机制)
调用:
org.springframework.aop.framework.JdkDynamicAopProxy
{
1、获取符合条件的“通知接受者”列表
1、ClassFilter匹配
2、MethodMatcher匹配 - 《调用的方法能命中,就符合》
2、创建ReflectiveMethodInvocation对象
1、执行《ReflectiveMethodInvocation对象.proceed()》(FilterChain模式)
1、调用“通知接受者”,并传入ReflectiveMethodInvocation
1、执行《业务》代码
2、执行调用《ReflectiveMethodInvocation对象.proceed()》,触发链条继续执行
}