spring源码解析bean初始化与依赖注入二

Easter79
• 阅读 526

前言

本文转自“天河聊技术”微信公众号

本次接着上次的介绍来解析bean初始化和依赖注入

正文

上一次跟踪到这个方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

// Instantiate the bean.   BeanWrapper instanceWrapper = null;   if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);   } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args);   } final Object bean = instanceWrapper.getWrappedInstance();   Class<?> beanType = instanceWrapper.getWrappedClass();   if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType;   }

// Allow post-processors to modify the merged bean definition.允许后处理器修改合并后的bean定义。   synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);         } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName,                  "Post-processing of merged bean definition failed", ex);         } mbd.postProcessed = true;      } }

// Eagerly cache singletons to be able to resolve circular references   // even when triggered by lifecycle interfaces like BeanFactoryAware.   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));   if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");      } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));   }

// Initialize the bean instance.   Object exposedObject = bean;   try { populateBean(beanName, mbd, instanceWrapper);      exposedObject = initializeBean(beanName, exposedObject, mbd);   } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex;      } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);      } }

if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false);      if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference;         } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName);            Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);            for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean);               } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName,                     "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");            } } } }

// Register bean as disposable.bean注册为一次性。   try { registerDisposableBeanIfNecessary(beanName, bean, mbd);   } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);   }

return exposedObject; }

找到这行代码

//        创建bean对象         instanceWrapper = createBeanInstance(beanName, mbd, args);

进入到这个方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point.      Class<?> beanClass = resolveBeanClass(mbd, beanName);

//    类必须是public,构造方法必须是public      if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName,               "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());      }

  Supplier<?> instanceSupplier = mbd.getInstanceSupplier();

     if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName);      }

//    如果工厂方法不为空,就用工厂方法创建bean      if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args);      }

  // Shortcut when re-creating the same bean...

     boolean resolved = false;      boolean autowireNecessary = false;      if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true;               autowireNecessary = mbd.constructorArgumentsResolved;            } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null);         } else { return instantiateBean(beanName, mbd);         } }

  // Need to determine the constructor...

     Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);      if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //       构造参数注入         return autowireConstructor(beanName, mbd, ctors, args);      }

  // No special handling: simply use no-arg constructor.无需特殊处理:只需使用无arg构造函数。

     return instantiateBean(beanName, mbd);   }

找到这一行代码

//     如果工厂方法不为空,就用工厂方法创建bean      if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args);      }

优先使用工厂方法创建bean对象

进入这个方法

org.springframework.beans.factory.support.ConstructorResolver#instantiateUsingFactoryMethod

这一行代码

//        默认类型自动装配,判断是否是构造参数装配         boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);

找到这一行代码

beanInstance = this.beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);

执行工厂方法创建对象

返回到这个方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance这一行代码

   构造方法注入            return autowireConstructor(beanName, mbd, null, null);

进入这个方法

org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor

public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,         @Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) {

  BeanWrapperImpl bw = new BeanWrapperImpl();

     this.beanFactory.initBeanWrapper(bw);

     Constructor<?> constructorToUse = null;      ArgumentsHolder argsHolderToUse = null;      Object[] argsToUse = null;

     if (explicitArgs != null) { argsToUse = explicitArgs;      } else { Object[] argsToResolve = null;         synchronized (mbd.constructorArgumentLock) { constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;            if (constructorToUse != null && mbd.constructorArgumentsResolved) { // Found a cached constructor...               argsToUse = mbd.resolvedConstructorArguments;               if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments;               } } } if (argsToResolve != null) { //          解析bean定义中的方法            argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);         } }

  if (constructorToUse == null) {
     // Need to resolve the constructor.判断是否是构造参数注入

        boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);         ConstructorArgumentValues resolvedValues = null;

        int minNrOfArgs;         if (explicitArgs != null) { minNrOfArgs = explicitArgs.length;         } else { ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();            resolvedValues = new ConstructorArgumentValues(); //          解析构造参数            minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);         }

     // Take specified constructors, if any.使用指定的构造函数(如果有的话)。

        Constructor\[\] candidates = chosenCtors;         if (candidates == null) { Class beanClass = mbd.getBeanClass();            try { candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());            } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName,                     "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);            } } AutowireUtils.sortConstructors(candidates);         int minTypeDiffWeight = Integer.MAX_VALUE;         Set<Constructor<?>> ambiguousConstructors = null;         LinkedList causes = null;

        for (Constructor candidate : candidates) { Class[] paramTypes = candidate.getParameterTypes();

           if (constructorToUse != null && argsToUse.length > paramTypes.length) { // Already found greedy constructor that can be satisfied ->               // do not look any further, there are only less greedy constructors left.               break;            } if (paramTypes.length < minNrOfArgs) { continue;            }

        ArgumentsHolder argsHolder;

           if (resolvedValues != null) { try { //                @ConstructorProperties注释解析                  String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);                  if (paramNames == null) { ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();                     if (pnd != null) { paramNames = pnd.getParameterNames(candidate);                     } } //                解析构造参数并转换成数组                  argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,                        getUserDeclaredConstructor(candidate), autowiring);               } catch (UnsatisfiedDependencyException ex) { if (this.beanFactory.logger.isTraceEnabled()) { this.beanFactory.logger.trace( "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);                  } // Swallow and try next constructor.                  if (causes == null) { causes = new LinkedList<>();                  } causes.add(ex);                  continue;               } } else { // Explicit arguments given -> arguments length must match exactly.               if (paramTypes.length != explicitArgs.length) { continue;               } argsHolder = new ArgumentsHolder(explicitArgs);            }

        int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
              argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));

           // Choose this constructor if it represents the closest match.            if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate;               argsHolderToUse = argsHolder;               argsToUse = argsHolder.arguments;               minTypeDiffWeight = typeDiffWeight;               ambiguousConstructors = null;            } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { if (ambiguousConstructors == null) { ambiguousConstructors = new LinkedHashSet<>();                  ambiguousConstructors.add(constructorToUse);               } ambiguousConstructors.add(candidate);            } }

     if (constructorToUse == null) {
        if (causes != null) {
           UnsatisfiedDependencyException ex = causes.removeLast();

              for (Exception cause : causes) { this.beanFactory.onSuppressedException(cause);               } throw ex;            } throw new BeanCreationException(mbd.getResourceDescription(), beanName,                  "Could not resolve matching constructor " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");         } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName,                  "Ambiguous constructor matches found in bean '" + beanName + "' " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousConstructors);         }

     if (explicitArgs == null) {
        argsHolderToUse.storeCache(mbd, constructorToUse);

        } }

  try {

//       bean初始化策略,如果容器中bean方法需要被覆盖,采用cglib创建子类         final InstantiationStrategy strategy = beanFactory.getInstantiationStrategy();         Object beanInstance;

        if (System.getSecurityManager() != null) { final Constructor<?> ctorToUse = constructorToUse;            final Object[] argumentsToUse = argsToUse;            beanInstance = AccessController.doPrivileged((PrivilegedAction) () -> //                初始化bean                  strategy.instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse),                  beanFactory.getAccessControlContext());         } else { beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);         }

     bw.setBeanInstance(beanInstance);

        return bw;      } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName,               "Bean instantiation via constructor failed", ex);      } }

返回到这个方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

使用默认构造参数初始化bean            return instantiateBean(beanName, mbd);

进入这个方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance;         final BeanFactory parent = this;         if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged((PrivilegedAction) () -> //                获取bean初始化策略并进行初始化                  getInstantiationStrategy().instantiate(mbd, beanName, parent),                  getAccessControlContext());         } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);         } BeanWrapper bw = new BeanWrapperImpl(beanInstance);         initBeanWrapper(bw);         return bw;      } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);      } }

   获取bean初始化策略并进行初始化                  getInstantiationStrategy().instantiate(mbd, beanName, parent),

进入这个方法

org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)

@Override   public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides.如果没有重写,不要使用CGLIB覆盖该类。      if (!bd.hasMethodOverrides()) { Constructor constructorToUse;         synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor) bd.resolvedConstructorOrFactoryMethod;            if (constructorToUse == null) { final Class clazz = bd.getBeanClass();               if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface");               } try { if (System.getSecurityManager() != null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction>) clazz::getDeclaredConstructor);                  } else { constructorToUse = clazz.getDeclaredConstructor();                  } bd.resolvedConstructorOrFactoryMethod = constructorToUse;               } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex);               } } } //       使用构造方法创建类         return BeanUtils.instantiateClass(constructorToUse);      } else { // Must generate CGLIB subclass.必须生成CGLIB子类         return instantiateWithMethodInjection(bd, beanName, owner);      } }

返回到这个方法

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean这一行代码

//        填充依赖注入的bean对象         populateBean(beanName, mbd, instanceWrapper);

进入org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean这个方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");         } else { // Skip property population phase for null instance.            return;         } }

  // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the

     // state of the bean before properties are set. This can be used, for example,      // to support styles of field injection.      boolean continueWithPropertyPopulation = true;

     if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;               if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false;                  break;               } } } }

  if (!continueWithPropertyPopulation) {
     return;

     }

  PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

//    如果是按名称注入或者按类型注入      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // Add property values based on autowire by name if applicable.如果可以的话,在autowire的基础上添加属性值。         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { //          按名称注入            autowireByName(beanName, mbd, bw, newPvs);         }

     // Add property values based on autowire by type if applicable.如果可以的话,按类型添加基于autowire的属性值。

        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { //          按类型注入            autowireByType(beanName, mbd, bw, newPvs);         }

     pvs = newPvs;

     }

  boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();

     boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

     if (hasInstAwareBpps || needsDepCheck) { if (pvs == null) { pvs = mbd.getPropertyValues();         } PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);         if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;                  pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);                  if (pvs == null) { return;                  } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs);         } }

  if (pvs != null) {
     applyPropertyValues(beanName, mbd, bw, pvs);

     } }

找到这行代码

//           按类型注入            autowireByType(beanName, mbd, bw, newPvs);

进入这个方法org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireByType

protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

  TypeConverter converter = getCustomTypeConverter();

     if (converter == null) { converter = bw;      }

  Set<String> autowiredBeanNames = new LinkedHashSet<>(4);

     String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);      for (String propertyName : propertyNames) { try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);            // Don't try autowiring by type for type Object: never makes sense,            // even if it technically is a unsatisfied, non-simple property.            if (Object.class != pd.getPropertyType()) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);               // Do not allow eager init for type matching in case of a prioritized post-processor.               boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());               DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); //             解析依赖值               Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);               if (autowiredArgument != null) { pvs.add(propertyName, autowiredArgument);               } for (String autowiredBeanName : autowiredBeanNames) { registerDependentBean(autowiredBeanName, beanName);                  if (logger.isDebugEnabled()) { logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'");                  } } autowiredBeanNames.clear();            } } catch (BeansException ex) { throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);         } } }

找到这行代码

   解析依赖值               Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);

进入这个方法

org.springframework.beans.factory.support.DefaultListableBeanFactory#createOptionalDependency

private Optional<?> createOptionalDependency( DependencyDescriptor descriptor, @Nullable String beanName, final Object... args) {

  DependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {
     @Override

        public boolean isRequired() { return false;         } @Override         public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) { return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) : super.resolveCandidate(beanName, requiredType, beanFactory));         } }; //    解析依赖      return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));   }

本次介绍到这里,下次继续。

最后

本次介绍到这里,以上内容仅供参考。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k