XML配置使用springaop源码解读
提示:假设已经阅读过spring的源码
文章目录
使用方法
<?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:context="http://www.springframework.org/schema/context"
//引入命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
//需要被通知的类,也是动态代理中的目标类
<bean id="person" class="com.srping.aop.Person"></bean>
//通知类
<bean id="myAdvice" class="com.srping.aop.MyAdvice"></bean>
//<aop:config>,会告诉spring容器使用AopNameSpaceHandler解析其下面的子标签
<aop:config>
//<aop:aspect>解析此标签是会在spring容器中注册一个org.springframework.aop.aspectj.AspectJPointcutAdvisor
<aop:aspect ref="myAdvice">
//前置通知,配置通知的方法和切入点
<aop:before method="log" pointcut="execution(void com.srping.aop.Person.eat())"/>
</aop:aspect>
</aop:config>
</beans>
源码阅读
AopNamespaceHandler.init()
public class AopNamespaceHandler extends NamespaceHandlerSupport {
public AopNamespaceHandler() {
}
public void init() {
//<aop:config>告诉spring容器使用ConfigBeanDefinitionParser解析子标签
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
//注解方式使用springAOP是开启自动扫描@Aspect,不在本篇阅读范围
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
ConfigBeanDefinitionParser.parse()
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
//向spring容器注册一个org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
//,在getBean的时候会实例化一个org.springframework.aop.config.internalAutoProxyCreator,这是一个 //beanPostPorocessor,可以创建目标类的代理对象
this.configureAutoProxyCreator(parserContext, element);
List<Element> childElts = DomUtils.getChildElements(element);
Iterator var5 = childElts.iterator();
while(var5.hasNext()) {
Element elt = (Element)var5.next();
String localName = parserContext.getDelegate().getLocalName(elt);
if ("pointcut".equals(localName)) {
this.parsePointcut(elt, parserContext);
} else if ("advisor".equals(localName)) {
this.parseAdvisor(elt, parserContext);
} else if ("aspect".equals(localName)) {
//解析<aop:aspect>,并且注册一个AspectJPointcutAdvisor到spring容器
this.parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
ConfigBeanDefinitionParser.parseAdvice()
private AbstractBeanDefinition parseAdvice(String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
RootBeanDefinition var12;
try {
this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
//设置通知方法名
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);
RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
AbstractBeanDefinition adviceDef = this.createAdviceDefinition(adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences);
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute("order")) {
advisorDefinition.getPropertyValues().add("order", aspectElement.getAttribute("order"));
}
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
var12 = advisorDefinition;
} finally {
this.parseState.pop();
}
return var12;
}
spring容器加载完成
getBean获取代理对象
//spring在populateBean之后会调用initializeBean方法,执行bean的init方法和bean的后置处理器(spring的源码知识点)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
//这里调用AspectAwareAdvisorAutoProxyCreator的postProcessAfterInitialization方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AbstractAutoProxyCreator.wrapIfNecessary()
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
**//最后创建person的代理对象**
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
DefaultAopProxyFactory.createAopProxy()
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//是否开启cglib自动代理或者是否有实现接口来觉得是采用JDK的自动代理还是Cglib的自动代理
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
总结
1.根据aop:config标签让spring容器加载beanDefinition的时候用AopNameSpaceHandler来解析
2.解析aop:advice时,会创建一个org.springframework.aop.aspectj.AspectJPointcutAdvisor#0对象,
对象有属性advice和pointcut,pointcut会根据配置文件的ponitcut表达式生成classFilter和methodMatch,后续会根据这个两个匹配器过滤哪些类和方法需要被代理和拦截
3.同时spring容器会注册一个AspectAwareAdvisorAutoProxyCreator的后置处理器
4.getBean时,会调用AspectAwareAdvisorAutoProxyCreator的后置处理方法返回代理对象
以上,仅代表个人阅读源码的理解