}
}
它实际上就是注册了四个解析器来处理四种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 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 beanDefinitions = new ArrayList();
List beanReferences = new ArrayList();
//获得已知的父类元素
List 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(“ 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 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 beanDefinitions, List 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 beanDefinitions, List 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 doGetBean(String name, Class 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() {
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 {
this.initializeAdvisorChain();
if (this.isSingleton()) {
//生产单例对象
return this.getSingletonInstance();
} else {
if (this.targetName == null) {
this.logger.warn(“Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the ‘targetName’ property.”);
}
//创建多例对象
return this.newPrototypeInstance();
}
}
看看如何获得单例对象的
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = this.freshTargetSource();
//还没有获得接口
if (this.autodetectInterfaces && this.getProxiedInterfaces().length == 0 && !this.isProxyTargetClass()) {
Class<?> targetClass = this.getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException(“Cannot determine target class for proxy”);
}
//给代理类设置接口
this.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
super.setFrozen(this.freezeProxy);
//创建AOP代理
this.singletonInstance = this.getProxy(this.createAopProxy());
}
return this.singletonInstance;
}
ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//如果当前配置不需要进一步优化,也不是代理目标类,存在可用的接口
if (!config.isOptimize() && !config.isProxyTargetClass()
&& !this.hasNoUserSuppliedProxyInterfaces(config)) {
//创建JDK动态代理
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 {
//如果目标类没有实现接口就创建CGLIB代理,否则创建JDK代理
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
JDK代理的实现
class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
最后,强调几点:
- 1. 一定要谨慎对待写在简历上的东西,一定要对简历上的东西非常熟悉。因为一般情况下,面试官都是会根据你的简历来问的; 能有一个上得了台面的项目也非常重要,这很可能是面试官会大量发问的地方,所以在面试之前好好回顾一下自己所做的项目;
- 2. 和面试官聊基础知识比如设计模式的使用、多线程的使用等等,可以结合具体的项目场景或者是自己在平时是如何使用的;
- 3. 注意自己开源的Github项目,面试官可能会挖你的Github项目提问;
我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!
以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目。
面试答案
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
中…(img-MStcmum4-1713427045393)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
最后,强调几点:
- 1. 一定要谨慎对待写在简历上的东西,一定要对简历上的东西非常熟悉。因为一般情况下,面试官都是会根据你的简历来问的; 能有一个上得了台面的项目也非常重要,这很可能是面试官会大量发问的地方,所以在面试之前好好回顾一下自己所做的项目;
- 2. 和面试官聊基础知识比如设计模式的使用、多线程的使用等等,可以结合具体的项目场景或者是自己在平时是如何使用的;
- 3. 注意自己开源的Github项目,面试官可能会挖你的Github项目提问;
我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!
以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目。
面试答案
[外链图片转存中…(img-AjJJ3OJq-1713427045393)]
[外链图片转存中…(img-shPBazwQ-1713427045393)]
[外链图片转存中…(img-GsndXK3e-1713427045394)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!