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

织梦修改网站标题万网域名注册查询

织梦修改网站标题,万网域名注册查询,众创空间网站建设方案,论基层门户网站的建设SpringBoot扩展篇#xff1a;Scope和Lazy源码解析 1. 研究主题及Demo2. 注册BeanDefinition3. 初始化属性3.1 解决依赖注入3.2 创建代理 ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary3.3 代理拦截处理3.4 单例bean与原型bean创建的区别 4. … SpringBoot扩展篇Scope和Lazy源码解析 1. 研究主题及Demo2. 注册BeanDefinition3. 初始化属性3.1 解决依赖注入3.2 创建代理 ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary3.3 代理拦截处理3.4 单例bean与原型bean创建的区别 4. 总结 1. 研究主题及Demo A class Component public class A {LazyAutowiredpublic B b;public B getB() {return b;} }B class Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) Component public class B { }测试类 SpringBootApplication public class WebApplication{public static void main(String[] args) {ConfigurableApplicationContext run SpringApplication.run(WebApplication.class, args);A a run.getBean(A.class);System.out.println(a.b);System.out.println(a.b);System.out.println(a.b);} }研究问题1为什么打印三次b对象的地址值不一样从源码角度分析Spring是如何实现的 研究问题2为什么会debug看到的是代理对象而打印出来的不是代理对象 2. 注册BeanDefinition 在Spring对Component扫描的时候会调用ClassPathBeanDefinitionScanner#doScan生成beandefinition对象可参考 SpringBoot 源码解析5ConfigurationClassPostProcessor整体流程和ComponentScan源码分析 protected SetBeanDefinitionHolder doScan(String... basePackages) {Assert.notEmpty(basePackages, At least one base package must be specified);SetBeanDefinitionHolder beanDefinitions new LinkedHashSet();for (String basePackage : basePackages) {SetBeanDefinition candidates findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());String beanName this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder new BeanDefinitionHolder(candidate, beanName);definitionHolder AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}此时Spring会通过AnnotationScopeMetadataResolver#resolveScopeMetadata扫描class上的Scope注解并通过candidate.setScope(scopeMetadata.getScopeName())将scope保存到beanDefinition中。 Override public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {ScopeMetadata metadata new ScopeMetadata();if (definition instanceof AnnotatedBeanDefinition) {AnnotatedBeanDefinition annDef (AnnotatedBeanDefinition) definition;AnnotationAttributes attributes AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);if (attributes ! null) {metadata.setScopeName(attributes.getString(value));ScopedProxyMode proxyMode attributes.getEnum(proxyMode);if (proxyMode ScopedProxyMode.DEFAULT) {proxyMode this.defaultProxyMode;}metadata.setScopedProxyMode(proxyMode);}}return metadata; }所以此时的B中的scope为prototype。 Spring默认为单例所以此时A中的scope为singleton。 3. 初始化属性 3.1 解决依赖注入 想要更加完善的了解Spring属性值注入可查看 SpringBoot扩展篇Spring注入 Autowired Resource 此时A对象已经创建完毕当对A对象的B字段赋值时会调用 DefaultListableBeanFactory#resolveDependency 实现依赖注入。 Override Nullable public Object resolveDependency(DependencyDescriptor descriptor, Nullable String requestingBeanName,Nullable SetString autowiredBeanNames, Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}else if (ObjectFactory.class descriptor.getDependencyType() ||ObjectProvider.class descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}else if (javaxInjectProviderClass descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else {Object result getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result null) {result doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;} }当getLazyResolutionProxyIfNecessary方法返回有值时就会返回当前值而当前值就是解析Lazy注解并对返回值进行了代理。 3.2 创建代理 ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary Override Nullable public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, Nullable String beanName) {return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null); }protected boolean isLazy(DependencyDescriptor descriptor) {for (Annotation ann : descriptor.getAnnotations()) {Lazy lazy AnnotationUtils.getAnnotation(ann, Lazy.class);if (lazy ! null lazy.value()) {return true;}}MethodParameter methodParam descriptor.getMethodParameter();if (methodParam ! null) {Method method methodParam.getMethod();if (method null || void.class method.getReturnType()) {Lazy lazy AnnotationUtils.getAnnotation(methodParam.getAnnotatedElement(), Lazy.class);if (lazy ! null lazy.value()) {return true;}}}return false; }protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final Nullable String beanName) {Assert.state(getBeanFactory() instanceof DefaultListableBeanFactory,BeanFactory needs to be a DefaultListableBeanFactory);final DefaultListableBeanFactory beanFactory (DefaultListableBeanFactory) getBeanFactory();TargetSource ts new TargetSource() {Overridepublic Class? getTargetClass() {return descriptor.getDependencyType();}Overridepublic boolean isStatic() {return false;}Overridepublic Object getTarget() {Object target beanFactory.doResolveDependency(descriptor, beanName, null, null);if (target null) {Class? type getTargetClass();if (Map.class type) {return Collections.emptyMap();}else if (List.class type) {return Collections.emptyList();}else if (Set.class type || Collection.class type) {return Collections.emptySet();}throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),Optional dependency not present for lazy injection point);}return target;}Overridepublic void releaseTarget(Object target) {}};ProxyFactory pf new ProxyFactory();pf.setTargetSource(ts);Class? dependencyType descriptor.getDependencyType();if (dependencyType.isInterface()) {pf.addInterface(dependencyType);}return pf.getProxy(beanFactory.getBeanClassLoader()); }isLazy方法判断是否需要懒加载。显然此时A对象的B字段上面有Lazy注解返回的是true。 buildLazyResolutionProxy方法创建ProxyFactory代理对象并返回该代理对象。当该代理对象调用方法时会回调getTarget() 方法从而从beanFactory中获取B对象。但是此时B对象是prototype类型不会保存到单例池singletonObjects中所以每次获取B对象的时候都是创建每次都是不同的对象。 3.3 代理拦截处理 private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private final AdvisedSupport advised;public DynamicAdvisedInterceptor(AdvisedSupport advised) {this.advised advised; }Override Nullable public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy null;boolean setProxyContext false;Object target null;TargetSource targetSource this.advised.getTargetSource();try {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);ListObject chain this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() Modifier.isPublic(method.getModifiers())) {// 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 methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation...retVal new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target ! null !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}} }在代理拦截器中 回调了target方法。 3.4 单例bean与原型bean创建的区别 AbstractBeanFactory#doGetBean 可以看到单例bean创建调用了getSingleton方法再从中回调createBean创建bean的而原型模式是直接调用createBean创建bean的。 DefaultSingletonBeanRegistry#getSingleton public Object getSingleton(String beanName, ObjectFactory? singletonFactory) {Assert.notNull(beanName, Bean name must not be null);synchronized (this.singletonObjects) {Object singletonObject this.singletonObjects.get(beanName);if (singletonObject null) {if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName,Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!));}if (logger.isDebugEnabled()) {logger.debug(Creating shared instance of singleton bean beanName );}beforeSingletonCreation(beanName);boolean newSingleton false;boolean recordSuppressedExceptions (this.suppressedExceptions null);if (recordSuppressedExceptions) {this.suppressedExceptions new LinkedHashSet();}try {singletonObject singletonFactory.getObject();newSingleton true;}catch (IllegalStateException ex) {// Has the singleton object implicitly appeared in the meantime -// if yes, proceed with it since the exception indicates that state.singletonObject this.singletonObjects.get(beanName);if (singletonObject null) {throw ex;}}catch (BeanCreationException ex) {if (recordSuppressedExceptions) {for (Exception suppressedException : this.suppressedExceptions) {ex.addRelatedCause(suppressedException);}}throw ex;}finally {if (recordSuppressedExceptions) {this.suppressedExceptions null;}afterSingletonCreation(beanName);}if (newSingleton) {addSingleton(beanName, singletonObject);}}return singletonObject;}}在单例bean创建的最后会调用addSingleton方法将创建好的bean放入到singletonObjects中而原型模式创建的bean不会 4. 总结 研究问题1为什么打印三次b对象的地址值不一样从源码角度分析Spring是如何实现的 研究问题2为什么会debug看到的是代理对象而打印出来的不是代理对象 Spring对A对象的B字段赋值的时候实际上是返回的是一个代理对象。而在打印一个对象的时候会打印这个对象的toString方法。此时会进入拦截器。而拦截器中会回调代理对象的getTarget方法。getTarget方法中会通过beanFactory获取B但是B是prototype不会将创建好的bean保存到singletonObjects中所以每次都会创建一个新的bean。
http://www.hkea.cn/news/14337500/

相关文章:

  • 昆山住房城乡建设局网站查询企业信息服务平台官网
  • 做seo网站的公司哪家好怎么搭建自己的电影网站
  • 昆山网站建设首页网站建设知名
  • 做网站需要向客户了解什么字体设计艺术字
  • 天津先进网站建设指导网站建设案例基本流程
  • 网站稳定性枣庄网站建设电话
  • 专业型企业网站有哪些设计店面装修
  • 罗庄建设局网站广东网站建设公司报价表
  • 济南住宅与房地产信息网官方网站门户网站开发流程
  • 陕西专业网站建设哪家好口碑好的广州做网站
  • 南宁大型网站建设广告公司排名
  • 上海做网站哪家公司好网页制作居中代码
  • 南通建设网站公司沈阳做企业网站
  • 做视频的网站带模板广州免费公司注册
  • 网站备案需要具备什么条件北京商场营业时间
  • 电子商务网站建设读书笔记没网站可以做seo吗
  • 台州网站建设咨询wordpress获取当前页地址
  • 网站标题怎么设置上海专业网站设计
  • 免费设计商标的网站建立网站所需的硬件和软件
  • 网站建设 pdf教程怎么查一个网站是谁做的
  • 重庆建设岗位培训网站网站建设的原则 流程
  • 苏州吴中区做网站价格网站建设服务器搭建
  • 制作网站电话在广告公司上班都干嘛
  • 网站做跳转会有什么影响可以做h5的网站
  • 网站备案图片杭州做网站的网络公司有哪些
  • 场外期权网站开发赤壁网站建设公司
  • 天津网址网站优化技术
  • 海口网站建设高端mes系统
  • 跨境电商平台有哪些分类seo技术交流
  • 电子商务网站域名p2p网站数据分析怎么做