当前位置: 首页 > news >正文

传媒公司取名资阳seo公司

传媒公司取名,资阳seo公司,网站注销主体,百度竞价排名价格文章目录 一、引言二、Spring AOP的使用三、Spring AOP的组件3.1 Pointcut源码3.2 Advice源码3.3 Advisor源码3.4 Aspect源码 四、Spring AOP源码刨析4.1 configureAutoProxyCreator源码解析4.2 parsePointcut源码解析4.3 parseAdvisor源码解析4.4 parseAspect源码解析4.5 小总… 文章目录 一、引言二、Spring AOP的使用三、Spring AOP的组件3.1 Pointcut源码3.2 Advice源码3.3 Advisor源码3.4 Aspect源码 四、Spring AOP源码刨析4.1 configureAutoProxyCreator源码解析4.2 parsePointcut源码解析4.3 parseAdvisor源码解析4.4 parseAspect源码解析4.5 小总结4.6 代理创建 五、总结 一、引言 AOP 是Spring框架的重点之一AOP全称为Aspect-Oriented Programming意思为面向切面编程这种编程方式是一种编程的范式。 AOP允许开发者将横向关注点如日志记录、事务管理等操作与业务逻辑分开来从而提高代码的模块化和可维护性。 下面从浅入深彻底搞懂Spring AOP的底层原理 注意本篇文章中使用的Spring框架的版本是4.0.0.RELEASE不同版本之间源码会有一点点不同但是大体逻辑差不多。 推荐阅读者需要对动态代理以及Spring IOC源码有一定了解如果不了解可以阅读以下文章 都2024年了还有人不懂动态代理么【Spring成神之路】一次SpringIOC源码之旅女朋友也成为了Spring大神 dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion4.0.0.RELEASE/version /dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion4.0.0.RELEASE/version /dependency二、Spring AOP的使用 UserService接口的定义 public interface UserService {String selectList(); }UserService接口实现类 public class UserServiceImpl implements UserService {Overridepublic String selectList() {System.out.println(小明, 小红, 小蓝);return 小明, 小红, 小蓝;} }AOP前置处理与后置处理 public class AOPUtil {private void before(JoinPoint joinPoint) {//获取方法签名Signature signature joinPoint.getSignature();//获取参数信息Object[] args joinPoint.getArgs();System.out.println(log--- signature.getName() I am before);}private void after(JoinPoint joinPoint) {//获取方法签名Signature signature joinPoint.getSignature();//获取参数信息Object[] args joinPoint.getArgs();System.out.println(log--- signature.getName() I am after);} }XML配置文件 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdbean idmessageService classspring.aop.UserServiceImpl/bean idaopUtil classspring.aop.AOPUtil/aop:configaop:aspect refaopUtilaop:pointcut idmyPoint expressionexecution(* spring.aop.UserService.selectList(..))/aop:before methodbefore pointcut-refmyPoint/aop:after methodafter pointcut-refmyPoint//aop:aspect/aop:config/beans测试类 public class AOPTest {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(application.xml);System.out.println(context 启动成功);UserService userService context.getBean(UserService.class);userService.selectList();} }我们只需要编写好切面的逻辑即可然后在xml配置文件配置后切面的方法的执行顺序即可实现在目标方法的前面或后面运行某个逻辑。 这当中到底发生了什么呢这些切面方法是何时被调用呢别急接着往下看 三、Spring AOP的组件 在阅读Spring AOP源码之前先来看看Spring AOP的几个组件这里源码会采取点到为止的方式并不深入讲解 Pointcut定义切面的匹配点主要是类和方法。比如上面例子的spring.aop.UserService.selectList(..)方法就是匹配点。Advice定义切面的行为即在匹配点执行的操作。也就是上面例子的aop:before和aop:afterAdvisor将Pointcut和Advice组合成一个对象也就是一个完整的切面。Aspect使用注解或XML配置方式定义的切面通常包含了多个Advisor 3.1 Pointcut源码 Pointcut是一个接口提供了getClassFilter方法和getMethodMatcher方法用于获取当前匹配的类和方法 public interface Pointcut {/*** 返回一个ClassFilter对象, 用于确定哪些类被匹配返回的对象不能为null*/ClassFilter getClassFilter();/*** 返回一个MethodMatcher对象用于确定哪些方法被匹配*/MethodMatcher getMethodMatcher();/*** Canonical Pointcut instance that always matches.*/Pointcut TRUE TruePointcut.INSTANCE;}AspectJExpressionPointcut是Pointcut的实现除了上面两个方法还提供了matches方法用于判断是否匹配。 public class AspectJExpressionPointcut extends AbstractExpressionPointcut implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {// 类的匹配public boolean matches(Class? targetClass) {}// 方法的匹配 public boolean matches(Method method, Class? targetClass, boolean hasIntroductions) {} } 3.2 Advice源码 Advice接口没有需要实现的方法它是用于定义切面的行为的比如方法前切入、方法后切入、环绕切入等等。 public interface Advice {}// 前置切入实现 public interface BeforeAdvice extends Advice {}// 后置切入实现 public interface AfterAdvice extends Advice {}3.3 Advisor源码 Advisor接口定义了getAdvice方法和isPerInstance方法 public interface Advisor {/*** 返回与该Advisor关联的Advice*/Advice getAdvice();/*** 返回这个Advice是否与特定的实例关联。*/boolean isPerInstance();}3.4 Aspect源码 Spring AOP并没有Aspect这个接口但是Aspect通常指下面这个 aop:aspect refaopUtil /aop:aspect四、Spring AOP源码刨析 阅读Spring AOP源码和阅读Spring IOC源码的步骤一样都是从读取application.xml配置文件开始。 因为AOP的配置信息是写在XML配置文件的所以肯定需要读取XML配置文件获取AOP相关的信息那么我们就看看这其中都做了什么吧。 直接定位到org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions这个方法不了解的可以先看看【Spring成神之路】一次SpringIOC源码之旅女朋友也成为了Spring大神 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)) {// 如果是bean 这些就走这个逻辑parseDefaultElement(ele, delegate);}else {// AOP走这个逻辑delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);} }既然知道parseCustomElement方法是处理aop标签的那么我们就进去看看是怎么个事 public BeanDefinition parseCustomElement(Element ele) {return parseCustomElement(ele, null); }public BeanDefinition parseCustomElement(Element ele, Nullable BeanDefinition containingBd) {// 获取当前的命名空间String namespaceUri getNamespaceURI(ele);if (namespaceUri null) {return null;}// 根据命名空间获取对应的处理器NamespaceHandler handler this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);if (handler null) {error(Unable to locate Spring NamespaceHandler for XML schema namespace [ namespaceUri ], ele);return null;}// 用处理器就行解析return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }parseCustomElement方法干三件事 获取元素的命名空间根据命名空间获取对应的处理器调用处理器的parse方法进行处理 继续DEBUG定位到了org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse方法 public BeanDefinition parse(Element element, ParserContext parserContext) {// 获取适合解析当前元素的BeanDefinitionParserBeanDefinitionParser parser findParserForElement(element, parserContext);// 进行解析并返回一个BeanDefinitionreturn (parser ! null ? parser.parse(element, parserContext) : null); }private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {// 获取元素的本地名称, 比如aop:config本地名称就是configString localName parserContext.getDelegate().getLocalName(element);// 获取该本地名称的解析器BeanDefinitionParser parser this.parsers.get(localName);if (parser null) {parserContext.getReaderContext().fatal(Cannot locate BeanDefinitionParser for element [ localName ], element);}return parser; }public BeanDefinition parse(Element element, ParserContext parserContext) {CompositeComponentDefinition compositeDef new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));parserContext.pushContainingComponent(compositeDef);// 设置自动代理创建器这是Spring AOP实现的核心configureAutoProxyCreator(parserContext, element);// 遍历当前标签下的标签不同的标签进行不同处理ListElement childElts DomUtils.getChildElements(element);for (Element elt: childElts) {String localName parserContext.getDelegate().getLocalName(elt);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; }4.1 configureAutoProxyCreator源码解析 configureAutoProxyCreator方法是Spring IOC的核心主要作用是确保 AspectJ 自动代理创建器被正确注册到 Spring 容器中 private void configureAutoProxyCreator(ParserContext parserContext, Element element) {AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); }public static void registerAspectJAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {BeanDefinition beanDefinition AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext); }该方法的目的是往Spring IOC容器中注册一个AspectjAwareAdvisorAutoProxyCreator其负责创建代理对象和实现切面编程。 4.2 parsePointcut源码解析 parsePointcut方法的主要作用是负责解析aop:pointcut标签 aop:pointcut idmyPoint expressionexecution(* spring.aop.UserService.selectList(..))/private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {// 获得String id pointcutElement.getAttribute(ID);// 获得切点表达式String expression pointcutElement.getAttribute(EXPRESSION);// 定义切点存储AbstractBeanDefinition pointcutDefinition null;try {// 将当前解析的切点ID压入解析状态栈this.parseState.push(new PointcutEntry(id));// 根据切点表达式创建切点定义pointcutDefinition createPointcutDefinition(expression);// 设置切点的来源pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));// 切点的Bean名称String pointcutBeanName id;if (StringUtils.hasText(pointcutBeanName)) {// 如果设置了id, 将切点注册到spring ioc容器中parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);}else {// 否则也是注入进spring ioc容器中并设置别名pointcutBeanName parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);}// 注册一个PointcutComponentDefinition组件parserContext.registerComponent(new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));}finally {// 从栈弹出this.parseState.pop();}return pointcutDefinition; }4.3 parseAdvisor源码解析 parseAdvisor方法负责解析advisor标签 private void parseAdvisor(Element advisorElement, ParserContext parserContext) {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);}// 解析切点Object pointcut parsePointcutProperty(advisorElement, parserContext);// 根据pointcut的类型将其添加到advisorDef的属性值中并注册相关的组件。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();} }4.4 parseAspect源码解析 parseAspect负责解析aspect标签 private void parseAspect(Element aspectElement, ParserContext parserContext) {// 获取ID值String aspectId aspectElement.getAttribute(ID);// 获取ref属性String aspectName aspectElement.getAttribute(REF);try {this.parseState.push(new AspectEntry(aspectId, aspectName));ListBeanDefinition beanDefinitions new ArrayList();ListBeanReference beanReferences new ArrayList();// 获得当前节点下的所有declare-parents子元素ListElement declareParents DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);for (int i METHOD_INDEX; i declareParents.size(); i) {Element declareParentsElement declareParents.get(i);// 解析节点并注册进IOC容器中beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));}// 获取当前节点的子节点NodeList nodeList aspectElement.getChildNodes();boolean adviceFoundAlready false;for (int i 0; i nodeList.getLength(); i) {Node node nodeList.item(i);// 是否是advice节点if (isAdviceNode(node, parserContext)) {// 是否是第一个advice节点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;}// 添加一个运行时bean引用到beanReferencesbeanReferences.add(new RuntimeBeanReference(aspectName));}// 如果节点是advice则调用parseAdvice方法解析它并创建一个顾问advisor的bean定义。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子元素。ListElement pointcuts DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);for (Element pointcutElement : pointcuts) {// 解析切点parsePointcut(pointcutElement, parserContext);}// 从解析上下文中弹出并注册包含的组件。parserContext.popAndRegisterContainingComponent();}finally {this.parseState.pop();} }总得来说就是解析标签将标签的内容包装成BeanDefinition并注册进IOC容器。 前面说到Advice就是一个切面的行为而parseAdvice方法就是负责解析这个切面行为的 private AbstractBeanDefinition parseAdvice(String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,ListBeanDefinition beanDefinitions, ListBeanReference beanReferences) {try {this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));// 解析advice节点中的 method 属性将其创建成一个 beanDefinition 对象RootBeanDefinition methodDefinition new RootBeanDefinition(MethodLocatingFactoryBean.class);methodDefinition.getPropertyValues().add(targetBeanName, aspectName);methodDefinition.getPropertyValues().add(methodName, adviceElement.getAttribute(method));methodDefinition.setSynthetic(true);// 关联aspectName对应的就是案例中的aopUtil包装为 SimpleBeanFactoryAwareAspectInstanceFactory 对象RootBeanDefinition aspectFactoryDef new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);aspectFactoryDef.getPropertyValues().add(aspectBeanName, aspectName);aspectFactoryDef.setSynthetic(true);// 解析切点并综合上面两个bean包装成AbstractAspectJAdviceAbstractBeanDefinition adviceDef createAdviceDefinition(adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,beanDefinitions, beanReferences);// 最终包装成AspectJPointcutAdvisorRootBeanDefinition 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));}// 注册advisorparserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);return advisorDefinition;}finally {this.parseState.pop();} }4.5 小总结 好吧估计有点绕晕了。就parseAspect方法来说主要的目的是想组装一个Advisor但是得先把把advice初始化这个时候就需要解析标签中的method等实例化出来methodDefinition。 有了methodDefinition就知道这个方法是前置增还是后置增强。接着实例化Pointcut等这些都是实例化完成后再再按照下图的组件关系组装出一个完整的Advisor这个Advisor有AOP的所有信息并保存在了IOC容器中。 既然切点、切面等信息以及包装好了代理对象是怎么创建返回的呢接着往下看。不过在此需要先加一点前置知识。 4.6 代理创建 在IOC源码篇的时候有讲解过org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization方法。 在org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons会实例化所有非延迟初始化的单例Bean 在这个方法中大致内容就是获取所有beanDefinitionNames然后进行遍历如果是属于FactoryBean则进行FactoryBean的处理否则正常处理。 ListString beanNames new ArrayList(this.beanDefinitionNames);for (String beanName : beanNames) {RootBeanDefinition bd getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() bd.isSingleton() !bd.isLazyInit()) {if (isFactoryBean(beanName)) {// ....省略}else {getBean(beanName);}} }因为AOP包装的Bean肯定不是FactoryBean因此直接进入getBean方法 public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false); }protected T T doGetBean(String name, Nullable ClassT requiredType, Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// 转化别名String beanName transformedBeanName(name);Object bean;// 提前检查单例缓存中是否有手动注册的单例对象这和循环依赖有关联以后会讲到Object sharedInstance getSingleton(beanName);if (sharedInstance ! null args null) {// 省略....}else {// 当对象都是单例的时候会尝试解决循环依赖的问题但是原型模式下如果存在循环依赖的情况那么直接抛出异常if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 省略若干行代码RootBeanDefinition mbd getMergedLocalBeanDefinition(beanName);String[] dependsOn mbd.getDependsOn();// 是单例if (mbd.isSingleton()) {sharedInstance getSingleton(beanName, () - {try {// 创建单例return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});bean getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}}return (T) bean; }整体代码比较啰嗦这里省略一些代码大体内容如下 转化bean的名字是否有循环依赖有的话解决循环依赖问题Bean属于单例进行创建单例 protected Object createBean(String beanName, RootBeanDefinition mbd, Nullable Object[] args)try {Object beanInstance doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace(Finished creating instance of bean beanName );}return beanInstance;}}protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Nullable Object[] args){// 根据执行bean使用对应的策略创建新的实例如工厂方法构造函数主动注入、简单初始化BeanWrapper instanceWrapper createBeanInstance(beanName, mbd, args);// 对bean的属性进行填充将各个属性值注入其中可能存在依赖于其他bean的属性则会递归初始化依赖的beanpopulateBean(beanName, mbd, instanceWrapper);// 执行初始化逻辑exposedObject initializeBean(beanName, exposedObject, mbd); }ok终于定位到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)这个方法了这个方法就是负责初始化Bean。 以上的内容属于IOC源码知识的补充下面正式开始AOP代理创建的源码解析 protected Object initializeBean(String beanName, Object bean, Nullable RootBeanDefinition mbd) {Object wrappedBean bean;if (mbd null || !mbd.isSynthetic()) {// 执行前置通知wrappedBean applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd ! null ? mbd.getResourceDescription() : null),beanName, Invocation of init method failed, ex);}if (mbd null || !mbd.isSynthetic()) {// 执行后置通知wrappedBean applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean; }前置通知和AOP没半毛钱关系主要关注执行后置通知 为什么AOP与后置通知有关系 还记不记得前面说过会向容器注入AspectjAwareAdvisorAutoProxyCreator这是类负责代理的创建 是的你没看错AspectjAwareAdvisorAutoProxyCreator是一个实现了BeanPostProcessor的类 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization方法的源码很简单就是调用postProcessAfterInitialization返回一个bean对当前的bean进行包装 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current processor.postProcessAfterInitialization(result, beanName);if (current null) {return result;}result current;}return result; }那AspectjAwareAdvisorAutoProxyCreator的postProcessAfterInitialization的实现是怎么样的 其实AspectjAwareAdvisorAutoProxyCreator并没有该方法的实现而是在其父类实现了org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization public Object postProcessAfterInitialization(Nullable Object bean, String beanName) {if (bean ! null) {// 获取当前bean的key如果beanName不为空则以beanName为key如果为FactoryBean类型// 前面还会添加符号如果beanName为空则以当前bean对应的class为keyObject cacheKey getCacheKey(bean.getClass(), beanName);// 判断这个bean是否正在在被代理如果正在被代理则不处理if (this.earlyProxyReferences.remove(cacheKey) ! bean) {// 进入需要被代理进行代理处理return wrapIfNecessary(bean, beanName, cacheKey);}}return bean; }protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 获取当前Bean的Advices和AdvisorsObject[] specificInterceptors getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);// 对Bean的代理状态缓存if (specificInterceptors ! DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 创建代理Object proxy createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));、// 缓存代理Bean的类型this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean; }着重关心一下createProxy看看创建代理是怎么个事 protected Object createProxy(Class? beanClass, Nullable String beanName,Nullable Object[] specificInterceptors, TargetSource targetSource) {// 给bean定义设置暴露属性if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}// 创建代理工厂ProxyFactory proxyFactory new ProxyFactory();// 将当前实例的配置复制到proxyFactoryproxyFactory.copyFrom(this);// 决定对于给定的Bean是否应该试应targetClass而不是接口代理if (!proxyFactory.isProxyTargetClass()) {// 检查使用JDK代理还是cglib代理if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {// 添加代理接口evaluateProxyInterfaces(beanClass, proxyFactory);}}// 构建增强器Advisor[] advisors buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);// 设置要代理的类proxyFactory.setTargetSource(targetSource);// 定制代理customizeProxyFactory(proxyFactory);// 控制代理工程被配置之后是否还允许修改通知默认值是falseproxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 完成上面这些之后开始创建代理对象return proxyFactory.getProxy(getProxyClassLoader()); }createAopProxy方法是根据代理目标选择JDK代理或者是Cglib代理代码挺容易看懂的就不解释了 public Object getProxy(Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader); }public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {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);} }至于getProxy方法JDK代理和CGLib代码都有不同的实现在都2024年了还有人不懂动态代理么有讲述过JDK代理和CGLIB代理的实现原理具体请看这篇文章。 五、总结 经过上面这么一步步过来这个Bean的代理对象就成功被内放进Spring IOC容器中当我们下次从容器getBean的时候就可以获取到代理的对象了。 虽然源码很复杂但是其实不需要记住每一步只需要记住Spring AOP实现的大体步骤思路即可 读取并解析配置文件将AOP的四大组件解析封装成Bean存放进IOC中向IOC注入一个AspectjAwareAdvisorAutoProxyCreator这是一个实现了BeanPostProcessor接口。这个非常重要这个是Spring AOP的核心在Spring IOC完成刷新之后会进行单例Bean的懒加载在懒加载的过程中会获取容器中的所有BeanPostProcessor实现类然后调用其postProcessAfterInitialization方法在AspectjAwareAdvisorAutoProxyCreator的实现会判断当前Bean需要被代理然后根据目标Bean是否实现接口等条件判断使用JDK代理还是CGlib代理然后返回代理类并放进容器 总体核心就这四点但里面的细节还有很多很多这篇文章就先写这吧。明天还要上班呢~
http://www.w-s-a.com/news/198247/

相关文章:

  • 郑州做网站齿轮网站排名怎么做 site
  • 船员专用网站开发建议wordpress 图片占用id
  • 桌面软件开发跟网站开发那个上海网站备案在哪里查询
  • 罗湖网站建设陕西省建设网官网住房和城乡厅官网
  • 做一个网站的详细教学wordpress 忘记用户名密码
  • 建设银行的网站是多少wordpress添加新页面跳转
  • 网站设计费用抓取网站访客qq号码
  • 驾校视频网站模板郑州网站建设价格
  • 上海 有哪些做网站的公司成都企业网站备案流程
  • 移动端快速建站的方法青海公司网站建设
  • 网站重新搭建程序要多少钱移动互联网应用的使用情况
  • 学建站论坛给别人做网站怎么赚钱吗
  • 响应式网站代码校友会网站建设的目的
  • 北京公司网站网站建设html模板
  • 专门做医疗器械的网站免费网页制作系统团队
  • 网站开发技术 html临夏网站建设
  • flash网站模板免费下载拍卖网站开发多少钱
  • 北京网站建设制作颍州网站建设
  • 网站制作报价表做网站上海公司
  • 简洁大气蓝色文章资讯网站百度搜索广告推广
  • 河南建设工程协会网站网站收银系统建设
  • 网站制作 服务企业网站案例展示
  • 咸宁网站建设wordpress手动降级
  • 昆明做网站建设怎么样做网站赚钱全攻略
  • 企业网站建设实战教程微信如何注册小程序
  • 做一件代发网站百度seo服务
  • 小说网站开发 公司可以做行程的网站
  • 古交市网站建设公司apk连接wordpress
  • 网页 网 址网站区别wordpress菜单居右
  • 网站建设搭建运营一台云服务器做多个网站