通过schema形式使用spring aop时,spring提供了相应的拓展,可以解析自定义的标签。下面是基于schema使用spring aop的一个示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<aop:config>
<aop:aspect id="countAgeCalls" ref="countingAdvice">
<aop:pointcut id="pc" expression="execution(* getAge())"/>
<aop:before pointcut-ref="pc" method="myBeforeAdvice" />
<aop:after pointcut-ref="pc" method="myAfterAdvice" />
<aop:after-returning pointcut-ref="pc" method="myAfterReturningAdvice" returning="age"/>
<aop:after-throwing pointcut-ref="pc" method="myAfterThrowingAdvice" throwing="ex"/>
<aop:around pointcut-ref="pc" method="myAroundAdvice"/>
</aop:aspect>
</aop:config>
<bean id="getNameCounter" class="org.springframework.tests.aop.advice.CountingBeforeAdvice"/>
<bean id="getAgeCounter" class="org.springframework.tests.aop.advice.CountingBeforeAdvice"/>
<bean id="testBean" class="org.springframework.tests.sample.beans.TestBean"/>
<bean id="countingAdvice" class="org.springframework.aop.config.CountingAspectJAdvice"/>
</beans>
解析aop标签
解析自定义标签需要实现NamespaceHandler
接口,spring内部提供的解析aop
标签的实现是AopNamespaceHandler
。
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());
}
}
从init()
方法中可以看出,其针对各种标签都有相应的解析器。下面让我们分析一下最常用的<aop:config>
以及<aop:aspectj-autoproxy>
标签。
首先让我们进入ConfigBeanDefinitionParser
类:
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 配置自动代理的构建器
configureAutoProxyCreator(parserContext, element);
// 获取子标签
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
// 获取标签名
String localName = parserContext.getDelegate().getLocalName(elt);
// 针对pointcut, advisor, aspect执行对应的解析
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
看到自动代理的构建器可能会比较疑惑,这个构建器有什么用?让我们思考一下如何对bean进行代理。Spring提供了BeanPostProcessor
及其子接口,可以在bean实例化之前对其进行修改,当然spring已经帮我们实现了自动化,不需要我们手动去注册这个BeanPostProcessor
,因此这个构建器的功能便是将其注册到BeanFactory
,以便之后创建bean的时候调用。
配置自动代理构建器
配置自动代理构建器共分为三步:
- 注册或者升级
internalAutoProxyCreator
bean - 设置
proxy-target-class
和expose-proxy
- 注册组件
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册或者升级internalAutoProxyCreator
// 优先级 AnnotationAwareAspectJAutoProxyCreator -> AspectJAwareAdvisorAutoProxyCreator -> InfrastructureAdvisorAutoProxyCreator
// 默认选用AspectJAwareAdvisorAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 设置proxy-target-class和expose-proxy
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
1. 注册或者升级bean internalAutoProxyCreator
spring内部规定构造器的beanName为internalAutoProxyCreator
,如果用户想要手动指定构建器,那么需要使用此名称作为beanName。
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果用户手动指定了internalAutoProxyCreator,那么检查是否需要升级
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果手动指定的bean的类型不是AspectJAwareAdvisorAutoProxyCreator,尝试进行升级
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 获取用户bean类型的优先级以及AspectJAwareAdvisorAutoProxyCreator的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
// 使用优先级更高的构建器
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 配置RootBeanDefinition并注册
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
当然,只能指定固定的三个构建器,无法自定义构建器。可选用的构建器及优先级如下:
private static int findPriorityForClass(Class<?> clazz) {
return APC_PRIORITY_LIST.indexOf(clazz);
}
private static int findPriorityForClass(@Nullable String className) {
for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
Class<?> clazz = APC_PRIORITY_LIST.get(i);
if (clazz.getName().equals(className)) {
return i;
}
}
throw new IllegalArgumentException(
"Class name [" + className + "] is not a known auto-proxy creator class");
}
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
// Set up the escalation list...
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
2. 设置proxy-target-class
和expose-proxy
spring aop的代理方式分为两种:jdk接口代理和cglib类代理。如果将proxy-target-class
属性设为true,那么将强制使用类代理。
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
// proxy-target-class
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// expose-proxy
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
如果proxy-target-class
和expose-proxy
设置为true,那么将其设置到BeanDefinition
中,创建bean实例时设置此属性。
3. 注册组件
最后注册组件。这一步spring内部是一个空实现,留待拓展。
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
parserContext.registerComponent(
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
}
}
解析子标签
配置完自动代理构建器后,需要解析pointcut
, advisor
, aspect
等子标签。
解析pointcut
子标签
pointcut
子标签的形式如下所示:
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
解析过程如下:
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
// 获取id属性
String id = pointcutElement.getAttribute(ID);
// 获取expression属性
String expression = pointcutElement.getAttribute(EXPRESSION);
AbstractBeanDefinition pointcutDefinition = null;
try {
this.parseState.push(new PointcutEntry(id));
// 构造pointcut BeanDefinition
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
// 将此pointcut BeanDefinition注册到容器中
String pointcutBeanName = id;
if (StringUtils.hasText(pointcutBeanName)) {
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
}
else {
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
parserContext.registerComponent(
new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
}
finally {
this.parseState.pop();
}
return pointcutDefinition;
}
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
// 表示pointcut的类是AspectJExpressionPointcut
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION, expression);
return beanDefinition;
}
如果没有设置id
属性或者id
属性的值为空白符,那么spring将会自动为其生成一个合法名称。
解析aspect
子标签
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
<aop:before pointcut-ref="businessService" method="monitor"/>
<aop:declare-parents
types-matching="com.xzy.myapp.service.*+"
implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
...
</aop:aspect>
aspect
标签下可以定义pointcut
, before
, after-returning
, after-throwing
, after
, around
, declare-parents
标签。
关于这几个标签的更多信息,请查看下面提供的官方文档链接:
了解了它们各自的作用后,让我们开始解析过程:
private void parseAspect(Element aspectElement, ParserContext parserContext) {
String aspectId = aspectElement.getAttribute(ID);
String aspectName = aspectElement.getAttribute(REF);
try {
this.parseState.push(new AspectEntry(aspectId, aspectName));
List<BeanDefinition> beanDefinitions = new ArrayList<>();
List<BeanReference> beanReferences = new ArrayList<>();
// 获取declare-parents子标签
List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
// 如果存在,执行相应解析
for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
Element declareParentsElement = declareParents.get(i);
beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
}
// We have to parse "advice" and all the advice kinds in one loop, to get the
// ordering semantics right.
NodeList nodeList = aspectElement.getChildNodes();
boolean adviceFoundAlready = false;
// 解析advice子标签
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (isAdviceNode(node, parserContext)) {
if (!adviceFoundAlready) {
adviceFoundAlready = true;
if (!StringUtils.hasText(aspectName)) {
parserContext.getReaderContext().error(
"<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",
aspectElement, this.parseState.snapshot());
return;
}
beanReferences.add(new RuntimeBeanReference(aspectName));
}
AbstractBeanDefinition advisorDefinition = parseAdvice(
aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
beanDefinitions.add(advisorDefinition);
}
}
AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
parserContext.pushContainingComponent(aspectComponentDefinition);
// 解析pointcut子标签
List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
for (Element pointcutElement : pointcuts) {
parsePointcut(pointcutElement, parserContext);
}
parserContext.popAndRegisterContainingComponent();
}
finally {
this.parseState.pop();
}
}
方法较为简单清晰,对每个类型的标签都尝试去解析。
解析declare-parents
private AbstractBeanDefinition parseDeclareParents(Element declareParentsElement, ParserContext parserContext) {
// 表示declare-parents的类为DeclareParentsAdvisor
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DeclareParentsAdvisor.class);
// 获取implement-interface和types-matching属性作为构造方法参数
builder.addConstructorArgValue(declareParentsElement.getAttribute(IMPLEMENT_INTERFACE));
builder.addConstructorArgValue(declareParentsElement.getAttribute(TYPE_PATTERN));
// 获取default-impl和delegate-ref属性,如果存在作为构造方法参数,这两个属性必须指定一个且仅一个
String defaultImpl = declareParentsElement.getAttribute(DEFAULT_IMPL);
String delegateRef = declareParentsElement.getAttribute(DELEGATE_REF);
if (StringUtils.hasText(defaultImpl) && !StringUtils.hasText(delegateRef)) {
builder.addConstructorArgValue(defaultImpl);
}
else if (StringUtils.hasText(delegateRef) && !StringUtils.hasText(defaultImpl)) {
builder.addConstructorArgReference(delegateRef);
}
else {
parserContext.getReaderContext().error(
"Exactly one of the " + DEFAULT_IMPL + " or " + DELEGATE_REF + " attributes must be specified",
declareParentsElement, this.parseState.snapshot());
}
AbstractBeanDefinition definition = builder.getBeanDefinition();
definition.setSource(parserContext.extractSource(declareParentsElement));
// 自动生成一个beanName并注册
parserContext.getReaderContext().registerWithGeneratedName(definition);
return definition;
}
解析advice
private AbstractBeanDefinition parseAdvice(
String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
try {
this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
// create the method factory bean
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);
// create instance factory definition
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
// register the pointcut
AbstractBeanDefinition adviceDef = createAdviceDefinition(
adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
beanDefinitions, beanReferences);
// configure the advisor
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
}
// register the final advisor
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
return advisorDefinition;
}
finally {
this.parseState.pop();
}
}
private AbstractBeanDefinition createAdviceDefinition(
Element adviceElement, ParserContext parserContext, String aspectName, int order,
RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
// 根据不同的advice类型获取对应的类
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
// 设置aspectName和declarationOrder属性
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
if (adviceElement.hasAttribute(RETURNING)) {
adviceDefinition.getPropertyValues().add(
RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
}
if (adviceElement.hasAttribute(THROWING)) {
adviceDefinition.getPropertyValues().add(
THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
}
if (adviceElement.hasAttribute(ARG_NAMES)) {
adviceDefinition.getPropertyValues().add(
ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
}
ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
// 解析pointcut-ref或者pointcut属性
Object pointcut = parsePointcutProperty(adviceElement, parserContext);
if (pointcut instanceof BeanDefinition) {
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
beanDefinitions.add((BeanDefinition) pointcut);
}
else if (pointcut instanceof String) {
RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
beanReferences.add(pointcutRef);
}
cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
return adviceDefinition;
}
private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
String elementName = parserContext.getDelegate().getLocalName(adviceElement);
if (BEFORE.equals(elementName)) {
return AspectJMethodBeforeAdvice.class;
}
else if (AFTER.equals(elementName)) {
return AspectJAfterAdvice.class;
}
else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
return AspectJAfterReturningAdvice.class;
}
else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
return AspectJAfterThrowingAdvice.class;
}
else if (AROUND.equals(elementName)) {
return AspectJAroundAdvice.class;
}
else {
throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
}
}
表示advice
的类都实现了Advice
接口。
解析advisor子标签
advisor
是使用切面的另一种形式,它是独属于spring aop的概念,是aspect
的一个更细化的形式,它只包含一个advice。更多信息请查看此处。
<aop:config>
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
<aop:advisor
pointcut-ref="businessService"
advice-ref="tx-advice"/>
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
解析过程如下:
private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
// 构造BeanDefinition
AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
String id = advisorElement.getAttribute(ID);
try {
this.parseState.push(new AdvisorEntry(id));
// 注册到容器
String advisorBeanName = id;
if (StringUtils.hasText(advisorBeanName)) {
parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
}
else {
advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
}
// 解析pointcut属性
Object pointcut = parsePointcutProperty(advisorElement, parserContext);
if (pointcut instanceof BeanDefinition) {
advisorDef.getPropertyValues().add(POINTCUT, pointcut);
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
}
else if (pointcut instanceof String) {
advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef));
}
}
finally {
this.parseState.pop();
}
}
private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
// advisor的表示类为DefaultBeanFactoryPointcutAdvisor
RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(advisorElement));
// 获取`advice-ref`属性
String adviceRef = advisorElement.getAttribute(ADVICE_REF);
if (!StringUtils.hasText(adviceRef)) {
parserContext.getReaderContext().error(
"'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot());
}
else {
advisorDefinition.getPropertyValues().add(
ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
}
// 尝试设置order属性
if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY));
}
return advisorDefinition;
}
各个标签的解析过程都比较简单,参照注释已经足以理解,不多赘述。
至此,aop:config
标签已经全部解析完成,让我们总结一下其中涉及到的各种定义。
- 自动代理构建器:beanName为
internalAutoProxyCreator
,beanClass为AspectJAwareAdvisorAutoProxyCreator
- pointcut:beanClass为
AspectJExpressionPointcut
- declare-parents:beanClass为
DeclareParentsAdvisor
- advice:beanClass为
AspectJPointcutAdvisor
- before:beanClass为
AspectJMethodBeforeAdvice
- after-returning:beanClass为
AspectJAfterReturningAdvice
- after-throwing:beanClass为
AspectJAfterThrowingAdvice
- after:beanClass为
AspectJAfterAdvice
- around:beanClass为
AspectJAroundAdvice
- advisor:beanClass为
DefaultBeanFactoryPointcutAdvisor
除了<aop:config>
标签,另一个常用标签为<aop:aspectj-autoproxy>
,它是用来解析基于注解的Aop定义。让我们看一下AspectJAutoProxyBeanDefinitionParser
类的parse
方法。
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
配置自动代理构建器与<aop:config>
类似,不过使用了优先级更高的AnnotationAwareAspectJAutoProxyCreator
。
当启动此配置时,默认检查所有使用了@AspectJ
注解的类。为了提供更精细化的控制,spring提供了<aop:include>
标签,你可以在name
属性中使用正则表达式来指定检查哪些使用了@AspectJ
注解的类。
<aop:aspectj-autoproxy>
<aop:include name="" />
</aop:aspectj-autoproxy>
private void extendBeanDefinition(Element element, ParserContext parserContext) {
BeanDefinition beanDef =
parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
if (element.hasChildNodes()) {
addIncludePatterns(element, parserContext, beanDef);
}
}
private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
NodeList childNodes = element.getChildNodes();
// 检查所有子节点,获取其name属性
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element) {
Element includeElement = (Element) node;
TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
valueHolder.setSource(parserContext.extractSource(includeElement));
includePatterns.add(valueHolder);
}
}
// 设置到includePatterns属性中
if (!includePatterns.isEmpty()) {
includePatterns.setSource(parserContext.extractSource(element));
beanDef.getPropertyValues().add("includePatterns", includePatterns);
}
}
使用代理增强bean
之前说过Spring提供了BeanPostProcessor
,可以在bean实例化之前对其进行处理,因此可以通过这种方式实现代理,让我们看一下自动代理构建器AspectJAwareAdvisorAutoProxyCreator
的继承层次:
可以发现它确实实现了BeanPostProcessor
接口。
Spring创建bean的其中一段过程如下,在doCreateBean
也就是真正的创建bean方法调用之前会先调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(Class<?>, String)
方法,执行用户或者Spring自定义的一些操作。
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 从配置元数据中解析此bean的class
// 因为配置元数据中只能保存String信息,所以需要使用类加载器加载这个类,并返回一个Class<?>对象
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 记录到缓存中,下次就不需要再从String中解析class了
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
// 对lookup-method,replaced-method方法注入进行预处理
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 调用后置处理器
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 创建bean实例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
resolveBeforeInstantiation
方法就是调用后置处理器的方法:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// mbd.beforeInstantiationResolved属性默认是被初始化为null的
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
// 如果这个bean factory中注册了一个InstantiationAwareBeanPostProcessor后置处理器
// InstantiationAwareBeanPostProcessor继承自BeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
了解了Spring创建bean的部分过程后,我们就可以正式开始探索AspectJAwareAdvisorAutoProxyCreator
是如何代理bean的了。
首先让我们看一下postProcessBeforeInstantiation
方法:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 构造缓存key,一般为bean的名称
Object cacheKey = getCacheKey(beanClass, beanName);
// 执行一些过滤操作,对于某些bean不进行代理
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 默认没有自定义的TargetSource
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
如果提供了自定义的TargetSource
,那会尝试根据此TargetSource
生成代理并返回。这个接口是Spring框架的内部接口,开发者不需要直接与其打交道,所以postProcessBeforeInstantiation
方法最终返回null,进行正常的bean创建流程。
TargetSource
的主要作用是为代理提供源对象,因此执行完增强逻辑后,代理对象可以把方法调用转发到源对象上,形成一个完整的调用链。
Spring默认使用SingletonTargetSource
,每一次请求代理对象时,SingletonTargetSource
都会返回同一个源对象,这也是我们所期待的。你也可以自定义TargetSource
或者使用Spring提供的其他TargetSource
,但是你的bean需要是prototype
才可以发挥它们的特性。
关于TargetSource
的更多信息,请查看Spring官方文档6.9. Using TargetSource Implementations。
除了postProcessBeforeInstantiation
方法外,在bean的创建过程中还会调用其他后置处理方法,如下所示:
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
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;
}
上面三个方法中,只有postProcessAfterInitialization
方法进行了一定的逻辑处理,wrapIfNecessary
方法便是进行将bean包装为代理的任务。
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;
}
// Create proxy if we have advice.
// 获取用于增强此bean的advice和advisor
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;
}
包装共分为两步,首先需要找到用于增强bean的advice
或者advisor
,然后构建代理对象将它们融合到一起。
寻找Advisor
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 寻找所有的advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 选择能到应用到此bean上的advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 拓展操作,留待子类实现
extendAdvisors(eligibleAdvisors);
// 排序可用的advisor
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
寻找操作共四步:
- 寻找所有的Advisor
- 选择能到应用到此bean上的Advisor
- 拓展Advisor
- 排序可用的Advisor
寻找所有的Advisor
这一步较为简单,从BeanFactory
中寻找所有类型为Advisor
的bean,并且实例化它们即可。
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
// 创建Advisor bean
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
在之前解析<aop:config>
标签时,一共生成了三种Advisor
:
- declare-parents:beanClass为
DeclareParentsAdvisor
- advisor:beanClass为
DefaultBeanFactoryPointcutAdvisor
- advice:beanClass为
AspectJPointcutAdvisor
因此,上一步获取到Advisor
便是配置文件中的declare-parents
,advisor
以及各种advice
。
选择能到应用到此bean上的Advisor
找到所有的Advisor
后,需要根据其types-matching
(declare-parents)或者pointcut
(advisor,advice)过滤出可用的Advisor
。
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 如果是引介Advisor(比如declare-parents)并且可以应用到此bean上
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 查找其他Advisor
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
由于这三种Advisor
的匹配方式不同,所以需要在不同方法种判断。其中DefaultBeanFactoryPointcutAdvisor
和AspectJPointcutAdvisor
都使用pointcut
匹配。
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
// 匹配declare-parents
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
// 匹配advisor和advice
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
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;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(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;
}
其中declare-parents
使用的是类匹配,而advisor
则是通过pointcut
使用方法匹配。具体的匹配逻辑此处不进行分析,感兴趣可以自行探索。
拓展Advisor
拓展操作一般留待子类实现,此处Spring增加了一个适配Advisor
,以使得AspectJAdvice
可以正常工作,此举是因为aspectj
的部分特性决定的。
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
// 如果使用到了AspectJAdvice,那么需要增加一个特殊的advisor来适配
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as this might eagerly
// instantiate a non-singleton AspectJ aspect...
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
/**
* Determine whether the given Advisor contains an AspectJ advice.
* @param advisor the Advisor to check
*/
private static boolean isAspectJAdvice(Advisor advisor) {
return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
(advisor instanceof PointcutAdvisor &&
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
}
isAspectJAdvice
方法较为复杂,涉及到了多个判断。如果你的aop:advisor
使用的自定义advice-ref
是AbstractAspectJAdvice
的子类,那么便算是AspectJAdvice
;同时,所有的before
,after
等advice
默认全都是AbstractAspectJAdvice
类型。目前的Poincut
的默认实现全都是AspectJExpressionPointcut
,当然,你也可以使用Spring提供的其他类型的Pointcut
来构造你的advisor
。
简而言之,使用spring默认的aop配置,isAspectJAdvice
的返回值将会为true。
排序可用的advisor
排序主要通过两种方式,第一种是实现Ordered
或者PriorityOrdered
接口,调用getOrder()
方法获取值。此处只建议实现Ordered
接口,由于之前在拓展Advisor
部分提到为了兼容AspectJAdvice
,spring会加入一个内置的Advisor
来进行适配,这个Advisor
实现了PriorityOrdered
接口,希望将其作为第一个Advisor
。因此,除非你比较熟悉这一方面的内容,否则不要实现PriorityOrdered
接口,以防造成意料之外的结果。
第二种方法是使用@Order
或者@Priority
注解。
如果两种方法都没有使用,那么返回最低优先级。另外,这两种方法的优先级为:Ordered
-> @Order
-> @Priority
。
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
AnnotationAwareOrderComparator.sort(advisors);
return advisors;
}
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
public int compare(@Nullable Object o1, @Nullable Object o2) {
return doCompare(o1, o2, null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
// ExposeInvocationInterceptor实现了PriorityOrdered,它永远作为advisor列表的第一个
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
// 获取顺序
int i1 = getOrder(o1, sourceProvider);
int i2 = getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
Integer order = null;
if (obj != null && sourceProvider != null) {
Object orderSource = sourceProvider.getOrderSource(obj);
if (orderSource != null) {
if (orderSource.getClass().isArray()) {
Object[] sources = ObjectUtils.toObjectArray(orderSource);
for (Object source : sources) {
order = findOrder(source);
if (order != null) {
break;
}
}
}
else {
order = findOrder(orderSource);
}
}
}
// 调用getOrder(obj)方法
return (order != null ? order : getOrder(obj));
}
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = findOrder(obj);
if (order != null) {
return order;
}
}
return Ordered.LOWEST_PRECEDENCE;
}
@Nullable
protected Integer findOrder(Object obj) {
return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}
protected Integer findOrder(Object obj) {
Integer order = super.findOrder(obj);
if (order != null) {
return order;
}
return findOrderFromAnnotation(obj);
}
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
if (order == null && obj instanceof DecoratingProxy) {
return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
}
return order;
}
static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) {
if (!(element instanceof Class)) {
return findOrder(annotations);
}
Object cached = orderCache.get(element);
if (cached != null) {
return (cached instanceof Integer ? (Integer) cached : null);
}
Integer result = findOrder(annotations);
orderCache.put(element, result != null ? result : NOT_ANNOTATED);
return result;
}
@Nullable
private static Integer findOrder(MergedAnnotations annotations) {
MergedAnnotation<Order> orderAnnotation = annotations.get(Order.class);
if (orderAnnotation.isPresent()) {
return orderAnnotation.getInt(MergedAnnotation.VALUE);
}
MergedAnnotation<?> priorityAnnotation = annotations.get(JAVAX_PRIORITY_ANNOTATION);
if (priorityAnnotation.isPresent()) {
return priorityAnnotation.getInt(MergedAnnotation.VALUE);
}
return null;
}
创建代理
获取到可用的Advisor
后,便可以使用它们配置代理。spring使用的代理共两种,jdk接口代理以及cglib类代理。
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);
// 此属性由proxy-target-class设置
if (!proxyFactory.isProxyTargetClass()) {
// 默认为false,除非@Configuration class被代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 设置代理接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 构造所有的Advisor,包含特定以及通用的,并转换为Advisor类型
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 增加Advisor,此处会增加declare-parents定义的接口
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 定制代理工厂,子类实现
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 获取代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
创建代理的过程如下:
- 暴露目标类。这一步是提供给
EventListener
使用。 - 其实便是配置代理工厂。如果使用jdk代理,那么需要预先查找代理接口,没有合适的接口的话便改为使用类代理。
- 定制代理工厂,子类实现。
- 获取代理对象。
构造Advisors
这一步是将通用的Advisor
也加入到Advisor
列表中,通用的Advisor
可以通过自定义自动代理构建器进行设置。例如:
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator">
<property name="interceptorNames" value="trace"/>
</bean>
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
// 获取通用Advisor,默认为空
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 转换为Advisor类型
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
private Advisor[] resolveInterceptorNames() {
BeanFactory bf = this.beanFactory;
ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
List<Advisor> advisors = new ArrayList<>();
// 可以通过自定义自动代理构建器,并通过interceptorNames属性设置
// <property name="interceptorNames" value="..." />
for (String beanName : this.interceptorNames) {
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
Object next = bf.getBean(beanName);
advisors.add(this.advisorAdapterRegistry.wrap(next));
}
}
return advisors.toArray(new Advisor[0]);
}
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
评估代理接口
这一步是评估beanClass实现的接口是否可以合法被jdk代理,主要是过滤spring的某些内置接口后,判断其他接口是否只是一个标记接口。如果是的话,那么将没有方法可供代理实现,因此需要使用cglib类代理。
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 获取这个beanClass的所有接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
// 寻找是否有可以合法代理的接口
for (Class<?> ifc : targetInterfaces) {
// 过滤某些不可用的接口
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 如果没有,则使用类代理
proxyFactory.setProxyTargetClass(true);
}
}
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
获取代理对象
首先创建Spring内置的aop代理对象,再通过aop代理对象获取真正的代理对象。
创建Spring内置的aop代理对象主要是判断使用jdk接口代理还是cglib代理:
- 自定义自动代理构建器,并设置
optimize
属性为true - 设置
proxy-target-class
为true - beanClass没有合理的代理接口
满足以上任意一条,并且beanClass不为接口或代理类,那么使用cglib代理;否则使用jdk代理。
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
// 只执行一次,首次调用此方法时激活
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 1. 自定义自动代理构建器,并设置optimize属性为true
// 2. 设置proxy-target-class为true
// 3. beanClass没有合理的代理接口
// 满足以上任意一条,并且beanClass不为接口或代理类,使用cglib代理;否则使用jdk代理
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
下面我们分别看一下jdk接口代理与cglib类代理的实现。
jdk接口代理
让我们进入其getProxy(ClassLoader)
方法:
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 补充代理接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 寻找代理接口是否定义了equals和hashCode方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 创建代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
首先补充代理接口。此方法会尝试加入三个Spring内置的接口SpringProxy
, Advised
和DecoratingProxy
,其中SpringProxy
一定会被增加。另两个接口也默认增加,如果自定义自动代理构建器,并设置其opaque
属性为true,那么Advised
接口将不会被增加。
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
// 获取之前查找的代理接口
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
if (specifiedInterfaces.length == 0) {
// No user-specified interfaces: check whether target class is an interface.
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
else if (Proxy.isProxyClass(targetClass)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
// 如果代理接口没有SpringProxy接口或其子接口,那么增加它
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
// isOpaque()方法默认返回false
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
int nonUserIfcCount = 0;
if (addSpringProxy) {
nonUserIfcCount++;
}
if (addAdvised) {
nonUserIfcCount++;
}
if (addDecoratingProxy) {
nonUserIfcCount++;
}
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
int index = specifiedInterfaces.length;
if (addSpringProxy) {
proxiedInterfaces[index] = SpringProxy.class;
index++;
}
if (addAdvised) {
proxiedInterfaces[index] = Advised.class;
index++;
}
if (addDecoratingProxy) {
proxiedInterfaces[index] = DecoratingProxy.class;
}
return proxiedInterfaces;
}
其中SpringProxy
接口是一个标记接口,表明这个实例是一个spring代理实现。Advised
接口可以在创建完代理对象后增加或者删除新的advisor
或者advice
,因此有一定的动态特性。DecoratingProxy
的作用在多重代理时获取最底层的源对象类型。关于Advised
接口的更多信息,请查看6.7. Manipulating Advised Objects。
其次判断所有的代理接口是否有实现equals
或者hashCode
方法,如果有那么便记录下来,当以后调用代理对象的这两个方法时,将优先使用用户自己实现的方法,否则spring将会提供这两个方法的实现。
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
for (Class<?> proxiedInterface : proxiedInterfaces) {
Method[] methods = proxiedInterface.getDeclaredMethods();
for (Method method : methods) {
if (AopUtils.isEqualsMethod(method)) {
this.equalsDefined = true;
}
if (AopUtils.isHashCodeMethod(method)) {
this.hashCodeDefined = true;
}
if (this.equalsDefined && this.hashCodeDefined) {
return;
}
}
}
}
最后,调用Proxy#newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
方法创建代理对象。
注意,JdkDynamicAopProxy
对象实现了InvocationHandler
接口,因此aop增强将在其invoke
方法中实现。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 处理equals和hashCode方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
// 处理DecoratingProxy接口定义的方法
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
// 处理Advised接口定义的方法
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 如果配置expose-proxy属性为true,那么设置当前代理对象
// 此处解释了((Pojo) AopContext.currentProxy()).bar()这类调用的原理
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 获取此方法的拦截链,即各种advice
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
此方法的实现虽然比较长,但是逻辑清晰,容易理解。
- 处理特殊方法,例如
equals
和hashCode
,以及之前补充接口时增加的接口方法 - 获取此方法的拦截链,即各种advice
- 如果拦截链为空,那么直接反射调用此方法;否则,按拦截链执行。
- 修饰返回值
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
// advisor和advice
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// createProxy方法中默认设置为true
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 判断方法是否匹配
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
// pointcut的表示类AspectJExpressionPointcut实现了此接口
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
// 如果declare-parents的type-matching能够匹配此类
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
// 从advisor中获取拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// declare-parents
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
获取拦截器的主要逻辑还是检验advisor是否可以应用到此方法上,我们不关心pointcut表达式解析器的实现,只看拦截器的获取。
方法主体分为三个if判断,不过spring内置的Advisor
实现类都是PointcutAdvisor
和IntroductionAdvisor
的子类,分别对应使用poincut
和declare-parents
。
从Advisor
中获取的拦截器类型必须为MethodInterceptor
,如果你自定义的advice没有实现此接口,只能通过适配器进行兼容。Spring提供了三种适配器MethodBeforeAdviceAdapter
, AfterReturningAdviceAdapter
, ThrowsAdviceAdapter
,分别适配MethodBeforeAdvice
, AfterReturningAdvice
和ThrowsAdvice
这三种advice。你也可以实现自己的Advice
,不过必须要实现Advice
接口,并且提供一个支持此Advice
的适配器,即实现AdvisorAdapter
接口,它是Spring提供的一个SPI。当然,你需要通过xml文件或者注解告知spring需要注册此实例,Spring会自动将它注册到GlobalAdvisorAdapterRegistry
中,如下所示:
public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
/**
* Specify the AdvisorAdapterRegistry to register AdvisorAdapter beans with.
* Default is the global AdvisorAdapterRegistry.
* @see GlobalAdvisorAdapterRegistry
*/
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AdvisorAdapter){
this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);
}
return bean;
}
}
AdvisorAdapterRegistrationManager
实现了BeanPostProcessor
接口,当创建你自定义的AdvisorAdapter
实例时,会注册它。
注意,获取到拦截advice后会进行缓存,因此之后再次调用此方法时性能会获得提升。
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
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[0]);
}
Spring也提供了硬编码使用代理的方法,即使用ProxyFactory
。此时可以自定义AdvisorChainFactory
和AdvisorAdapterRegistry
,并使用自定义的适配器。如下所示:
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SerializablePerson());
factory.addInterface(Person.class);
factory.addAdvice(new CountingBeforeAdvice());
factory.setExposeProxy(true);
// 自定义AdvisorChainFactory,实现getInterceptorsAndDynamicInterceptionAdvice方法
// 自定义AdvisorAdapterRegistry,并在getInterceptorsAndDynamicInterceptionAdvice方法中使用
AdvisorChainFactory chainFactory = new MyAdvisorChainFactory();
factory.setAdvisorChainFactory(chainFactory);
}
}
class MyAdvisorChainFactory implements AdvisorChainFactory, Serializable {
private AdvisorAdapterRegistry registry = new MyAdvisorAdapterRegistry();
@NotNull
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
@NotNull Advised config, @NotNull Method method, Class<?> targetClass) {
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
for(Advisor advisor : advisors) {
interceptorList.add(registry.getInterceptors(advisor));
}
return interceptorList;
}
}
class MyAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>();
public MyAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@NotNull
@Override
public MethodInterceptor[] getInterceptors(@NotNull Advisor advisor) throws UnknownAdviceTypeException {
return new MethodInterceptor[0];
}
@NotNull
@Override
public Advisor wrap(@NotNull Object advice) throws UnknownAdviceTypeException {
return null;
}
public void registerAdvisorAdapter(@NotNull AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
获取到拦截器链后,如果拦截器链为空,那么通过反射直接调用,不过spring做了一点预处理适配参数。当调用方法拥有可变参数,并且实参类型与形参类型不同,spring会进行类型适配。
static Object[] adaptArgumentsIfNecessary(Method method, @Nullable Object[] arguments) {
if (ObjectUtils.isEmpty(arguments)) {
return new Object[0];
}
if (method.isVarArgs()) {
if (method.getParameterCount() == arguments.length) {
Class<?>[] paramTypes = method.getParameterTypes();
int varargIndex = paramTypes.length - 1;
Class<?> varargType = paramTypes[varargIndex];
if (varargType.isArray()) {
Object varargArray = arguments[varargIndex];
// 实参为数组并且其类型与形参不同
if (varargArray instanceof Object[] && !varargType.isInstance(varargArray)) {
Object[] newArguments = new Object[arguments.length];
System.arraycopy(arguments, 0, newArguments, 0, varargIndex);
// 获取形参元素类型
Class<?> targetElementType = varargType.getComponentType();
// 获取实参数组长度
int varargLength = Array.getLength(varargArray);
// 构造数组,类型为形参元素类型
Object newVarargArray = Array.newInstance(targetElementType, varargLength);
System.arraycopy(varargArray, 0, newVarargArray, 0, varargLength);
newArguments[varargIndex] = newVarargArray;
return newArguments;
}
}
}
}
return arguments;
}
如果拦截器链不为空,那么将构造ReflectiveMethodInvocation
,在其中进行拦截器的执行。
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 拦截器调用完成后,调用连接点,即方法本身
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 逐个调用拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
此处会对InterceptorAndDynamicMethodMatcher
进行特殊处理。由于某些aspectj pointcut
表达式拥有动态特性,所有需要根据具体参数再次匹配是否适用此拦截器。
此处,我们分析最常用的五种advice:before
, after
, after-returning
, after-throwing
和around
。
首先是before
advice对应的MethodBeforeAdviceInterceptor
。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
protected Object invokeAdviceMethod(
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
throws Throwable {
// 进行参数绑定,然后调用advice方法
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
MethodBeforeAdviceInterceptor
的调用便是先调用与之关联的advice
方法,然后再调用mi.proceed()
回到调用链。
after
对应的拦截器为AspectJAfterAdvice
:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
先继续调用链,调用链执行完成后再调用其advice
方法。
after-returning
对应的拦截器为AfterReturningAdviceInterceptor
:
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
也是先继续调用链,调用链执行完成后获取其返回值,然后调用其advice
方法。
after-throwing
对应的拦截器为AspectJAfterThrowingAdvice
:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
around
对应的拦截器为AspectJAroundAdvice
:
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
它们具体的执行顺序与配置文件中的定义顺序相关。
拦截链执行完成后,spring会对返回值进行修饰。当方法的返回值为this
,并且这个方法的返回类型是类型兼容的,并且这个bean没有实现RawTargetAccess
接口,那么spring会帮助把这个this
替换为代理对象。
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
至此,jdk接口代理的实现分析完毕。