Spring 源码解析(二)AOP,java 基础课程百度云
面向切面编程
Spring 的两大特性之一
是 OOP 的重要补充
代码解耦
关注横向关系
分离核心业务和非核心业务
应用场景有:事务管理、缓存管理、日志收集、权限控制、性能监控等
Aspect(切面) 哪些方法会被切中,切中后如何处理
PointCut(切入点)定义哪些方法被切中,Java 的 AOP 只支持方法,其他语言可以支持构造方法或属性
JoinPoint(连接点)被切中的方法
Advise(通知)在原有方法的基础上,加入新的功能
前置 before
后置 after
环绕 around
返回后置 afterReturning
异常后置 afterThrowing
Weave(织入)在原有方法的功能上,加入新功能过程
==================================================================
解析源码需要带着目的来看,这次主要看两个重点:
aop 有关的标签是如何解析并注册到 IOC 容器中的
获得 JavaBean 时是如何产生动态代理的
接下来我们看看 Spring 源码中进行 AOP 的过程,首先我们要找到 AOP 的入口。
这不像 IOC 的源码有具体的类和方法可以直接进入,AOP 是自动进行的,它是在哪里导入到 Spring 中的呢?
我们可以回想一下 IOC 的过程:
有一个步骤是分别解析默认的命名空间和自定义的命名空间,aop 就属于自定义命名空间,会不会在这里 Spring 做了特殊的处理?
我们从这个位置进入看看:
DefaultBeanDefinitionDocumentReader 类:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element)node;
if (delegate.isDefaultNamespace(ele)) {
//解析默认命名空间
this.parseDefaultElement(ele, delegate);
} else {
delegate.parseCustomElement(ele);
}
}
}
} else {
//解析自定义命名空间
delegate.parseCustomElement(root);
}
}
进入解析自定义命名空间的方法,首先是拿到元素的 URI,对于 AOP 就是http://www.springframework.org/schema/aop,然后通过 URI 找到对应的命名空间处理器 NamespaceHandler,对应 AOP 的处理器就是 AOPNamespaceHandler,然后由处理器来进行解析。
BeanDefinitionParserDelegate 类:
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
//获得 Element 的 URI
String namespaceUri = this.getNamespaceURI(ele);
//通过 URI 找到处理器
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 {
//解析 XML 元素
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
}
看下 AopNamespaceHandler 类
public class AopNamespaceHandler extends NamespaceHandlerSupport {
public AopNamespaceHandler() {
}
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBean
DefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
它实际上就是注册了四个解析器来处理四种 aop 标签:
config ConfigBeanDefinitionParser
aspectj-autoproxy AspectJAutoProxyBeanDefinitionParser
scoped-proxy ScopedProxyBeanDefinitionDecorator
spring-configured SpringConfiguredBeanDefinitionParser
我们最常用的是 aop:config 标签,接下来我们看看 ConfigBeanDefinitionParser 类
这个类中主要有个 parse 方法,第一个参数是 XML 元素,第二个是解析器上下文
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
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)) {
this.parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
下面部分通过标签名称的判断,解析 config 标签中的 pointcut、advisor 和 aspect 这三个标签。先看看切面部分的解析:
private void parseAspect(Element aspectElement, ParserContext parserContext) {
//获得 aspect 的 id 和 name 值
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();
//获得已知的父类元素
List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, "declare-parents");
//解析所有的父类元素
for(int i = 0; i < declareParents.size(); ++i) {
Element declareParentsElement = (Element)declareParents.get(i);
beanDefinitions.add(this.parseDeclareParents(declareParentsElement, parserContext));
}
NodeList nodeList = aspectElement.getChildNodes();
boolean adviceFoundAlready = false;
//遍历所有子节点
for(int i = 0; i < nodeList.getLength(); ++i) {
Node node = nodeList.item(i);
//判断是否是 before、after、after-returning、after-throwing、around
if (this.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));
}
//解析每个 advice,并添加到集合中
AbstractBeanDefinition advisorDefinition = this.parseAdvice(aspectName, i, aspectElement, (Element)node, parserContext, beanDefinitions, beanReferences);
beanDefinitions.add(advisorDefinition);
}
}
AspectComponentDefinition aspectComponentDefinition = this.createAspectComponentDefinition(aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
parserContext.pushContainingComponent(aspectComponentDefinition);
List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, "pointcut");
Iterator var21 = pointcuts.iterator();
//解析 aspect 中所有的 pointcut 子节点
while(var21.hasNext()) {
Element pointcutElement = (Element)var21.next();
this.parsePointcut(pointcutElement, parserContext);
}
//发送注册完成的事件
parserContext.popAndRegisterContainingComponent();
} finally {
this.parseState.pop();
}
}
在看看 Advice 的解析:
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)));
//创建 BeanDefinition,保存方法的信息
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);
//创建 BeanDefinition,保存工厂信息
RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);
//把前面解析出来的内容包装起来,创建一个 Advise 方法的 BeanDefinition
AbstractBeanDefinition adviceDef = this.createAdviceDefinition(adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences);
//所有内容最后放在这个 BeanDefinition 中
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
//将 Advice 的定义添加到 Advisor 的构造方法参数中
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
//解析 aspect 的 order 属性
if (aspectElement.hasAttribute("order")) {
advisorDefinition.getPropertyValues().add("order", aspectElement.getAttribute("order"));
}
//在 IOC 容器中注册 Advisor 的 BeanDefinition
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
var12 = advisorDefinition;
} finally {
this.parseState.pop();
}
return var12;
}
创建 Advise 定义的方法,这个方法把前面解析的一系列内容放到 BeanDefinition 中。
private AbstractBeanDefinition createAdviceDefinition(Element adviceElement, ParserContext parserContext, String aspectName, int order, RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
//获得 Advise 的类型,并创建一个 BeanDefinition
RootBeanDefinition adviceDefinition = new RootBeanDefinition(this.getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));
adviceDefinition.getPropertyValues().add("aspectName", aspectName);
adviceDefinition.getPropertyValues().add("declarationOrder", order);
if (adviceElement.hasAttribute("returning")) {
adviceDefinition.getPropertyValues().add("returningName", adviceElement.getAttribute("returning"));
}
if (adviceElement.hasAttribute("throwing")) {
adviceDefinition.getPropertyValues().add("throwingName", adviceElement.getAttribute("throwing"));
}
if (adviceElement.hasAttribute("arg-names")) {
adviceDefinition.getPropertyValues().add("argumentNames", adviceElement.getAttribute("arg-names"));
}
ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(0, methodDef);
Object pointcut = this.parsePointcutProperty(adviceElement, parserContext);
if (pointcut instanceof BeanDefinition) {
cav.addIndexedArgumentValue(1, pointcut);
beanDefinitions.add((BeanDefinition)pointcut);
} else if (pointcut instanceof String) {
RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String)pointcut);
cav.addIndexedArgumentValue(1, pointcutRef);
beanReferences.add(pointcutRef);
}
cav.addIndexedArgumentValue(2, 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".equals(elementName)) {
return AspectJAfterReturningAdvice.class;
} else if ("after-throwing".equals(elementName)) {
return AspectJAfterThrowingAdvice.class;
} else if ("around".equals(elementName)) {
return AspectJAroundAdvice.class;
} else {
throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
}
}
到这里 aop:config 标签里的所有内容都被解析出来了,包装成 BeanDefinition,并注册到 IOC 的容器中了。
再看动态代理是如何产生的,所有的 Bean 包括代理,都可以通过 getBean 来获得,我们从这条线索跟下去:
AbstractApplicationContext 类:
public Object getBean(String name) throws BeansException {
this.assertBeanFactoryActive();
//这里
return this.getBeanFactory().getBean(name);
}
AbstractBeanFactory 类:
public Object getBean(String name) throws BeansException {
//这里
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
跟进去
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isDebugEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//这里 获得 JavaBean 实例对象
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
...
}
}
跟进去
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
} else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
Object object = null;
if (mbd == null) {
object = this.getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean)beanInstance;
if (mbd == null && this.containsBeanDefinition(beanName)) {
mbd = this.getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = mbd != null && mbd.isSynthetic();
//这里 通过工厂 Bean 获得对象
object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
} else {
return beanInstance;
}
}
跟进去
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
} else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
Object object = null;
if (mbd == null) {
object = this.getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean)beanInstance;
if (mbd == null && this.containsBeanDefinition(beanName)) {
mbd = this.getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = mbd != null && mbd.isSynthetic();
//这里
object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
} else {
return beanInstance;
}
}
跟进去
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && this.containsSingleton(beanName)) {
synchronized(this.getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 这里
object = this.doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
if (object != null && shouldPostProcess) {
try {
object = this.postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable var9) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var9);
}
}
this.factoryBeanObjectCache.put(beanName, object != null ? object : NULL_OBJECT);
}
}
return object != NULL_OBJECT ? object : null;
}
} else {
Object object = this.doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = this.postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable var11) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var11);
}
}
return object;
}
}
跟进去
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = this.getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
//这里
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException var7) {
throw new BeanCurrentlyInCreationException(beanName, var7.toString());
} catch (Throwable var8) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
}
if (object == null && this.isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
} else {
return object;
}
}
这个 getObject 就是从工厂中拿到对象了,FactoryBean 有很多种实现类,我们往下跟 ProxyFactoryBean 也就是代理的工厂 Bean。
ProxyFactoryBean
public Object getObject() throws BeansException {
评论