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

做网站代理拉不到人中国佛山手机网站建设

做网站代理拉不到人,中国佛山手机网站建设,郑州网站建设优化,wordpress出境游前言 最近做项目#xff0c;发现了springboot2.7.x在参数initiate的时候可以反复初始化#xff0c;而且首次异常后#xff0c;第二次成功居然也可以启动#xff0c;通过查看源代码发现了问题根源#xff0c;且在springboot高版本3.x#xff0c;就出现了了Configuration的…前言 最近做项目发现了springboot2.7.x在参数initiate的时候可以反复初始化而且首次异常后第二次成功居然也可以启动通过查看源代码发现了问题根源且在springboot高版本3.x就出现了了Configuration的 enforceUniqueMethods 的加载配置项应该是springboot发现并修复了这个问题。 Spring Boot 2.7.14 使用oracle jdk8和springboot 2.7.14按照如下方式初始化bean Configuration EnableConfigurationProperties(DemoProperties.class) public class DemoConfig {Autowiredprivate DemoProperties demoProperties;Beanpublic FirstBean initFirstBean(NeedDemoBean needDemoBean) {FirstBean firstBean new FirstBean();firstBean.setNeedDemoBean(needDemoBean);return firstBean;}BeanConditionalOnMissingBean(DemoBean.class)public DemoBean initDemoBean(DemoProperties demoProperties) {DemoBean demoBean new DemoBean();demoBean.setDemoProperties(demoProperties);return demoBean;}BeanConditionalOnBean(DemoBean.class)public NeedDemoBean initNeedDemoBean(DemoBean demoBean){NeedDemoBean needDemoBean new NeedDemoBean();needDemoBean.setDemoBean(demoBean);return needDemoBean;}BeanConditionalOnMissingBean(DemoBean.class)public NeedDemoBean initNeedDemoBean(){return new NeedDemoBean();} } 其中DemoBean首次初始化抛出异常 public class DemoBean {private DemoProperties demoProperties;private static boolean isFirstInit true;public DemoProperties getDemoProperties() {return demoProperties;}public void setDemoProperties(DemoProperties demoProperties) {this.demoProperties demoProperties;}PostConstructpublic void init(){haha();}public void haha(){if (isFirstInit) {System.out.println(1111111111111111111111);isFirstInit false;throw new RuntimeException(first init error.........................);}System.out.println(22222222222222222222222222);} }springboot启动完成后可以正常启动日志也不会出现异常 这里就很诡异了为什么初始化2次为什么抛的异常不见了 原理分析  首先分析bean的加载顺序 步骤就是如图 但是为什么DemoBean初始化2次原因在于参数依赖初始化bean依赖注入与相同的beanId的beanFactory的创建过程 源代码分析 从源码上验证我们上面的分析说明分析的是对的 Spring默认安装beanNames的顺序创建bean但是我们可以控制顺序这里就存在控制的情况同时这个官方注解也说明了non-lazy的单例 org.springframework.beans.factory.support.DefaultListableBeanFactory的 preInstantiateSingletons 证明Configuration的bean先创建然后创建FirstBean根据程序栈确实如此 但是这个方法有参数根据依赖注入原则需要对参数bean进行create org.springframework.beans.factory.support.ConstructorResolver 问题就在这里在参数依赖注入创建bean的过程抛出异常会被吞掉在后面的逻辑处理只有多次创建bean都失败才会抛出最后一次的异常 问题就出在这里实际上多个BeanId相同的的时候如果有条件控制会不受条件控制那么会初始化就可能发生多次其中一次成功即可且没有注解限制笔者明明注解了 ConditionalOnBean 但是因为依赖注入没有Bean就会创建Bean关键是也没提示抛的异常也看不到 /*** Instantiate the bean using a named factory method. The method may be static, if the* bean definition parameter specifies a class, rather than a factory-bean, or* an instance variable on a factory object itself configured using Dependency Injection.* pImplementation requires iterating over the static or instance methods with the* name specified in the RootBeanDefinition (the method may be overloaded) and trying* to match with the parameters. We dont have the types attached to constructor args,* so trial and error is the only way to go here. The explicitArgs array may contain* argument values passed in programmatically via the corresponding getBean method.* param beanName the name of the bean* param mbd the merged bean definition for the bean* param explicitArgs argument values passed in programmatically via the getBean* method, or {code null} if none (- use constructor argument values from bean definition)* return a BeanWrapper for the new instance*/public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, Nullable Object[] explicitArgs) {BeanWrapperImpl bw new BeanWrapperImpl();this.beanFactory.initBeanWrapper(bw);Object factoryBean;Class? factoryClass;boolean isStatic;String factoryBeanName mbd.getFactoryBeanName();if (factoryBeanName ! null) {if (factoryBeanName.equals(beanName)) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,factory-bean reference points back to the same bean definition);}factoryBean this.beanFactory.getBean(factoryBeanName);if (mbd.isSingleton() this.beanFactory.containsSingleton(beanName)) {throw new ImplicitlyAppearedSingletonException();}this.beanFactory.registerDependentBean(factoryBeanName, beanName);factoryClass factoryBean.getClass();isStatic false;}else {// Its a static factory method on the bean class.if (!mbd.hasBeanClass()) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,bean definition declares neither a bean class nor a factory-bean reference);}factoryBean null;factoryClass mbd.getBeanClass();isStatic true;}Method factoryMethodToUse null;ArgumentsHolder argsHolderToUse null;Object[] argsToUse null;if (explicitArgs ! null) {argsToUse explicitArgs;}else {Object[] argsToResolve null;synchronized (mbd.constructorArgumentLock) {factoryMethodToUse (Method) mbd.resolvedConstructorOrFactoryMethod;if (factoryMethodToUse ! null mbd.constructorArgumentsResolved) {// Found a cached factory method...argsToUse mbd.resolvedConstructorArguments;if (argsToUse null) {argsToResolve mbd.preparedConstructorArguments;}}}if (argsToResolve ! null) {argsToUse resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);}}//刚刚启动这些是没有的if (factoryMethodToUse null || argsToUse null) {// Need to determine the factory method...// Try all methods with this name to see if they match the given arguments.factoryClass ClassUtils.getUserClass(factoryClass);ListMethod candidates null;//bean id唯一这也是解决办法之一说明Spring设计的时候是考虑的if (mbd.isFactoryMethodUnique) {if (factoryMethodToUse null) {factoryMethodToUse mbd.getResolvedFactoryMethod();}if (factoryMethodToUse ! null) {candidates Collections.singletonList(factoryMethodToUse);}}//读取method就是Bean的方法通过class鉴别if (candidates null) {candidates new ArrayList();Method[] rawCandidates getCandidateMethods(factoryClass, mbd);for (Method candidate : rawCandidates) {if (Modifier.isStatic(candidate.getModifiers()) isStatic mbd.isFactoryMethod(candidate)) {candidates.add(candidate);}}}//一个method的情况显式参数为null没有构造函数if (candidates.size() 1 explicitArgs null !mbd.hasConstructorArgumentValues()) {Method uniqueCandidate candidates.get(0);if (uniqueCandidate.getParameterCount() 0) {mbd.factoryMethodToIntrospect uniqueCandidate;synchronized (mbd.constructorArgumentLock) {mbd.resolvedConstructorOrFactoryMethod uniqueCandidate;mbd.constructorArgumentsResolved true;mbd.resolvedConstructorArguments EMPTY_ARGS;}bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));return bw;}}//多个的时候考虑顺序排序if (candidates.size() 1) { // explicitly skip immutable singletonListcandidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);}ConstructorArgumentValues resolvedValues null;boolean autowiring (mbd.getResolvedAutowireMode() AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);int minTypeDiffWeight Integer.MAX_VALUE;SetMethod ambiguousFactoryMethods null;int minNrOfArgs;if (explicitArgs ! null) {minNrOfArgs explicitArgs.length;}else {// We dont have arguments passed in programmatically, so we need to resolve the// arguments specified in the constructor arguments held in the bean definition.if (mbd.hasConstructorArgumentValues()) {ConstructorArgumentValues cargs mbd.getConstructorArgumentValues();resolvedValues new ConstructorArgumentValues();minNrOfArgs resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}else {minNrOfArgs 0;}}DequeUnsatisfiedDependencyException causes null;// 多个method实际上只有一个成功就行for (Method candidate : candidates) {int parameterCount candidate.getParameterCount();if (parameterCount minNrOfArgs) {ArgumentsHolder argsHolder;Class?[] paramTypes candidate.getParameterTypes();//显式参数是外部传入的参数比如配置文件等不是依赖注入Bean参数if (explicitArgs ! null) {// Explicit arguments given - arguments length must match exactly. // 有显式参数的情况if (paramTypes.length ! explicitArgs.length) {continue;}argsHolder new ArgumentsHolder(explicitArgs);}else { //一般情况都不是显式参数// Resolved constructor arguments: type conversion and/or autowiring necessary.try {String[] paramNames null;ParameterNameDiscoverer pnd this.beanFactory.getParameterNameDiscoverer();if (pnd ! null) {paramNames pnd.getParameterNames(candidate);}//这个很关键只要一次成功即可argsHolder createArgumentArray(beanName, mbd, resolvedValues, bw,paramTypes, paramNames, candidate, autowiring, candidates.size() 1);}catch (UnsatisfiedDependencyException ex) {if (logger.isTraceEnabled()) {logger.trace(Ignoring factory method [ candidate ] of bean beanName : ex);}// Swallow and try next overloaded factory method.if (causes null) {causes new ArrayDeque(1);}causes.add(ex);//异常虽然加了但是for循环一下次如果创建成功就不会失败continue; // 异常就Contine}}int typeDiffWeight (mbd.isLenientConstructorResolution() ?argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));// Choose this factory method if it represents the closest match.if (typeDiffWeight minTypeDiffWeight) {factoryMethodToUse candidate;argsHolderToUse argsHolder; //这个决定异常是否抛出argsToUse argsHolder.arguments; //这个是参数同一个对象minTypeDiffWeight typeDiffWeight;ambiguousFactoryMethods null;}// Find out about ambiguity: In case of the same type difference weight// for methods with the same number of parameters, collect such candidates// and eventually raise an ambiguity exception.// However, only perform that check in non-lenient constructor resolution mode,// and explicitly ignore overridden methods (with the same parameter signature).else if (factoryMethodToUse ! null typeDiffWeight minTypeDiffWeight !mbd.isLenientConstructorResolution() paramTypes.length factoryMethodToUse.getParameterCount() !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {if (ambiguousFactoryMethods null) {ambiguousFactoryMethods new LinkedHashSet();ambiguousFactoryMethods.add(factoryMethodToUse);}ambiguousFactoryMethods.add(candidate);}}} // 这里就是多个method的情况结束一个method就不存多次创建一次成功就好的情况异常直接抛了if (factoryMethodToUse null || argsToUse null) {//跟刚刚的赋值对应if (causes ! null) { //只有创建bean失败才会抛出异常UnsatisfiedDependencyException ex causes.removeLast();for (Exception cause : causes) {this.beanFactory.onSuppressedException(cause);}//创建bean的异常就是这里抛出的throw ex; //如果有异常就抛}ListString argTypes new ArrayList(minNrOfArgs);if (explicitArgs ! null) {for (Object arg : explicitArgs) {argTypes.add(arg ! null ? arg.getClass().getSimpleName() : null);}}else if (resolvedValues ! null) {SetValueHolder valueHolders new LinkedHashSet(resolvedValues.getArgumentCount());valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());valueHolders.addAll(resolvedValues.getGenericArgumentValues());for (ValueHolder value : valueHolders) {String argType (value.getType() ! null ? ClassUtils.getShortName(value.getType()) :(value.getValue() ! null ? value.getValue().getClass().getSimpleName() : null));argTypes.add(argType);}}String argDesc StringUtils.collectionToCommaDelimitedString(argTypes);throw new BeanCreationException(mbd.getResourceDescription(), beanName,No matching factory method found on class [ factoryClass.getName() ]: (mbd.getFactoryBeanName() ! null ?factory bean mbd.getFactoryBeanName() ; : ) factory method mbd.getFactoryMethodName() ( argDesc ). Check that a method with the specified name (minNrOfArgs 0 ? and arguments : ) exists and that it is (isStatic ? static : non-static) .);}else if (void.class factoryMethodToUse.getReturnType()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,Invalid factory method mbd.getFactoryMethodName() on class [ factoryClass.getName() ]: needs to have a non-void return type!);}else if (ambiguousFactoryMethods ! null) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,Ambiguous factory method matches found on class [ factoryClass.getName() ] (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): ambiguousFactoryMethods);}if (explicitArgs null argsHolderToUse ! null) {mbd.factoryMethodToIntrospect factoryMethodToUse;argsHolderToUse.storeCache(mbd, factoryMethodToUse);}}bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));return bw;} 就会出现明明异常了而且因为相同的Bean ID多个其中一个创建的bean创建成功 但是确把依赖Bean创建成功了明显不符合ConditionOnBean的实际情况 实际Spring执行顺序如下 Spring Boot 3.1.x 需要JDK 17LTS因为JDK8已经不支持了 Spring增加了 enforceUniqueMethods 如果不加默认情况会报错 org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Configuration class DemoConfig contains overloaded Bean methods with name initNeedDemoBean. Use unique method names for separate bean definitions (with individual conditions etc) or switch Configuration.enforceUniqueMethods to false. Offending resource: class path resource [org/example/boot/demo/config/DemoConfig.class]at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:72)at org.springframework.context.annotation.ConfigurationClass.validate(ConfigurationClass.java:233)at org.springframework.context.annotation.ConfigurationClassParser.validate(ConfigurationClassParser.java:205)at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:416)at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:287)at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:344)at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115)at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:771)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:589)at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:436)at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)at org.example.boot.demo.BootMain.main(BootMain.java:9) 如果我们主动设置为false呢 Use unique method names for separate bean definitions (with individual conditions etc) or switch Configuration.enforceUniqueMethods to false. 结果也会一样 因为org.springframework.beans.factory.support.ConstructorResolver代码没变仅仅是增加了扫描检查而已默认就是要检查的相当于源头规避问题让你充分知道但是解决这个问题由你自己解决 总结 这个问题实际上出现不是很频繁但是如果不经意就会出现我们不可预知的问题尤其是初始化的情况不同条件初始化绝对不一样出现这种问题我们很难知道根源因为异常被吞了启动也OK。当然解决问题是不使用id相同的Bean创建方式因为如果异常只要其中一个Bean创建成功即可成功没异常我们发现不了问题如果没有异常相同的Bean id会被后创建的Bean替代但是在相同id的时候是都会尝试创建ConditionOnXxx就不会执行这个会跟我们需要的情况相违背。当然如果升级SpringBoot 3.x启动就会提示问题也是一个解决之道类似Spring5.3收拢循环依赖一样循环依赖虽然Spring也能解决其中一些情况比如Set注入构造函数不行但是终有隐患这个问题同理所以Spring也是直接把开关设置默认true启动直接保错解决思路同理。
http://www.zqtcl.cn/news/710964/

相关文章:

  • mysql数据库做网站广州网站seo地址
  • 福建省住房和城乡建设厅网站电话网站开发项目步骤
  • 网站注册域名多少钱淘宝网商城
  • 做架构图的网站网站和网店的区别
  • 做红包网站简单个人网站设计
  • 新手学做网站pdf手wordpress修改搜索框
  • 做湲兔费网站视颍如何通过查询网站注册时间
  • 重庆cms建站模板南通网站建设推广优化
  • 合肥网站建设的公司新闻类网站如何做量化统计
  • 好用的在线地图网站十六局集团门户网
  • 网站开发数据库连接失败广州网站建站平台
  • 鄂尔多斯北京网站建设加盟网站建设的内容
  • 网站 被 抄袭不属于营销型网站的特点
  • 浙江英文网站建设互联网公司排名2021完整版
  • 完美代码的网站python开发工具
  • 餐饮网站开发参考文献网站建设500错误代码
  • 网站开发关键技术网站自动推广软件免费
  • 前端学习网站南阳东莞网站建设公司哪家好
  • 关于做网站的了解点wordpress小程序插曲
  • PHP网站开发与管理设计心得个人可以做聊天网站备案吗
  • 开公司可以在哪些网站做推广上海画册设计
  • 成都高新区规划建设局网站网络营销方式有哪些?举例说明
  • 国家企业信用公信系统入口seo服务
  • 个人网站网页模板室内装修设计自学软件
  • 什么网站可以做告白的网页网站模板套用湖南岚鸿
  • 膜结构网站推广怎么做怎样把网站上传到空间
  • 三维网站是怎么做的商城网站 运营
  • 程序员网站开发框架无锡网络公司网站建设app微信公众号平
  • 中关村网站建设网络营销策划书范文
  • 电商网站建设与课程设计科技网站模版