spring中bean配置和bean注入

Easter79
• 阅读 799

1 bean与spring容器的关系

spring中bean配置和bean注入

Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。

1 bean配置

bean配置有三种方法:

  • 基于xml配置Bean
  • 使用注解定义Bean
  • 基于java类提供Bean定义信息

1.1 基于xml配置Bean

 对于基于XML的配置,Spring 2.0以后使用Schema的格式,使得不同类型的配置拥有了自己的命名空间,是配置文件更具扩展性。

spring中bean配置和bean注入

①默认命名空间:它没有空间名,用于Spring Bean的定义;

②xsi命名空间:这个命名空间用于为每个文档中命名空间指定相应的Schema样式文件,是标准组织定义的标准命名空间;

③aop命名空间:这个命名空间是Spring配置AOP的命名空间,是用户自定义的命名空间。

命名空间的定义分为两个步骤:第一步指定命名空间的名称;第二步指定命名空间的Schema文档样式文件的位置,用空格或回车换行进行分分隔。

1.1.1 Bean基本配置

在Spring容器的配置文件中定义一个简要Bean的配置片段如下所示:

spring中bean配置和bean注入

一般情况下,Spring IOC容器中的一个Bean即对应配置文件中的一个,这种镜像对应关系应该容易理解。其中id为这个Bean的名称,通过容器的getBean("foo")即可获取对应的Bean,在容器中起到定位查找的作用,是外部程序和Spring IOC容器进行交互的桥梁。class属性指定了Bean对应的实现类。

下面是基于XML的配置文件定义了两个简单的Bean:

spring中bean配置和bean注入


spring中bean配置和bean注入

1.1.2 依赖注入

  1. 属性注入
  2. 构造函数注入
  3. 工厂方式注入

1.2 使用注解定义Bean

我们知道,Spring容器成功启动的三大要件分别是:Bean定义信息、Bean实现类以及Spring本身。如果采用基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现。

下面是使用注解定义一个DAO的Bean:

spring中bean配置和bean注入

package com.baobaotao.anno;

import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; //①通过Repository定义一个DAO的Bean

@Component("userDao") public class UserDao {

}

spring中bean配置和bean注入

在①处,我们使用@Component注解在UserDao类声明处对类进行标注,它可以被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean。

它和以下的XML配置是等效的:

除了@Component以外,Spring提供了3个功能基本和@Component等效的注解,它们分别用于对DAO、Service及Web层的Controller进行注解,所以也称这些注解为Bean的衍型注解:(类似于xml文件中定义Bean

  • @Repository:用于对DAO实现类进行标注;
  • @Service:用于对Service实现类进行标注;
  • @Controller:用于对Controller实现类进行标注;

之所以要在@Component之外提供这三个特殊的注解,是为了让注解类本身的用途清晰化,此外Spring将赋予它们一些特殊的功能。

1.2.1 使用注解配置信息启动spring容器

Spring提供了一个context的命名空间,它提供了通过扫描类包以应用注解定义Bean的方式:

spring中bean配置和bean注入

<context:component-scan base-package="com.baobaotao.anno"/>

spring中bean配置和bean注入

在①处声明context命名空间,在②处即可通过context命名空间的component-scan的base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。

如果仅希望扫描特定的类而非基包下的所有类,你们可以使用resource-pattern属性过滤特定的类,如下所示:

< context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/ >

这里我们将基类包设置为com.baobaotao,默认情况下resource-pattern属性的值为"**/*.class",即基类包里的所有类。这里我们设置为"anno/*.class",则Spring仅会扫描基包里anno子包中的类。

1.3 基于java类提供Bean定义

在普通的POJO类中只要标注@Configuration注解,就可以为spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供了一个Bean的定义信息。

spring中bean配置和bean注入

package com.baobaotao.conf;

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; //①将一个POJO标注为定义Bean的配置类 @Configuration public class AppConf { //②以下两个方法定义了两个Bean,以提供了Bean的实例化逻辑 @Bean public UserDao userDao(){ return new UserDao();
}

@Bean
public LogDao logDao(){
    return new LogDao();
}
//③定义了logonService的Bean
@Bean
public LogonService logonService(){
    LogonService logonService = new LogonService();
            //④将②和③处定义的Bean注入到LogonService Bean中
    logonService.setLogDao(logDao());
    logonService.setUserDao(userDao());
    return logonService;
}

}

spring中bean配置和bean注入

①处在APPConf类的定义处标注了@Configuration注解,说明这个类可用于为Spring提供Bean的定义信息。类的方法处可以标注@Bean注解,Bean的类型由方法返回值类型决定,名称默认和方法名相同,也可以通过入参显示指定Bean名称,如@Bean(name="userDao").直接在@Bean所标注的方法中提供Bean的实例化逻辑。

在②处userDao()和logDao()方法定义了一个UserDao和一个LogDao的Bean,它们的Bean名称分别是userDao和logDao。在③处,又定义了一个logonService Bean,并且在④处注入②处所定义的两个Bean。

因此,以上的配置和以下XML配置时等效的:

基于java类的配置方式和基于XML或基于注解的配置方式相比,前者通过代码的方式更加灵活地实现了Bean的实例化及Bean之间的装配,但后面两者都是通过配置声明的方式,在灵活性上要稍逊一些,但是配置上要更简单一些。

 2 Bean注入

Bean注入的方式有两种,一种是在XML中配置,此时分别有属性注入、构造函数注入和工厂方法注入;另一种则是使用注解的方式注入 @Autowired,@Resource,@Required

2.1 在xml文件中配置依赖注入

2.1.1 属性注入

属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。

属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。

spring中bean配置和bean注入

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware;

public class LogonService implements BeanNameAware{

private LogDao logDao;

private UserDao userDao;

public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}

public void setLogDao(LogDao logDao) {
    this.logDao = logDao;
}

public LogDao getLogDao() {
    return logDao;
}
public UserDao getUserDao() {
    return userDao;
}

public void setBeanName(String beanName) {
    System.out.println("beanName:"+beanName);        
}

public void initMethod1(){
    System.out.println("initMethod1");
}
public void initMethod2(){
    System.out.println("initMethod2");
}

}

spring中bean配置和bean注入

bean.xml配置

spring中bean配置和bean注入

spring中bean配置和bean注入

2.1.2 构造方法注入

使用构造函数注入的前提是Bean必须提供带参数的构造函数。例如

spring中bean配置和bean注入

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware;

public class LogonService implements BeanNameAware{

public LogonService(){}

public LogonService(LogDao logDao, UserDao userDao) {
    this.logDao = logDao;
    this.userDao = userDao;
}

private LogDao logDao;

private UserDao userDao;

public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}

public void setLogDao(LogDao logDao) {
    this.logDao = logDao;
}

public LogDao getLogDao() {
    return logDao;
}
public UserDao getUserDao() {
    return userDao;
}

public void setBeanName(String beanName) {
    System.out.println("beanName:"+beanName);        
}

public void initMethod1(){
    System.out.println("initMethod1");
}
public void initMethod2(){
    System.out.println("initMethod2");
}

}

spring中bean配置和bean注入

bean.xml配置

spring中bean配置和bean注入

<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
<bean id="userDao" class="com.baobaotao.anno.UserDao"/>

spring中bean配置和bean注入

2.1.3 工厂方法注入

非静态工厂方法:

有些工厂方法是非静态的,即必须实例化工厂类后才能调用工厂放。

spring中bean配置和bean注入

package com.baobaotao.ditype;

public class CarFactory { public Car createHongQiCar(){ Car car = new Car(); car.setBrand("红旗CA72"); return car; }

public static Car createCar(){ Car car = new Car(); return car; } }

spring中bean配置和bean注入

工厂类负责创建一个或多个目标类实例,工厂类方法一般以接口或抽象类变量的形式返回目标类实例,工厂类对外屏蔽了目标类的实例化步骤,调用者甚至不用知道具体的目标类是什么。

spring中bean配置和bean注入

<!-- 工厂方法-->
<bean id="carFactory" class="com.baobaotao.ditype.CarFactory" />
<bean id="car5" factory-bean="carFactory" factory-method="createHongQiCar">
</bean>

spring中bean配置和bean注入

静态工厂方法:

很多工厂类都是静态的,这意味着用户在无须创建工厂类实例的情况下就可以调用工厂类方法,因此,静态工厂方法比非静态工厂方法的调用更加方便。

spring中bean配置和bean注入

<bean id="car6" class="com.baobaotao.ditype.CarFactory"
    factory-method="createCar"></bean>

spring中bean配置和bean注入

2.2 使用注解的方式注入

2.2.1 使用@Autowired进行自动注入

Spring通过@Autowired注解实现Bean的依赖注入,下面是一个例子:

spring中bean配置和bean注入

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; //① 定义一个Service的Bean(不需要在XML中定义Bean) @Service public class LogonService implements BeanNameAware{ //② 分别注入LogDao及UserDao的Bean(不需要在XML中定义property属性注入) @Autowired(required=false) private LogDao logDao; @Autowired @Qualifier("userDao") private UserDao userDao;

public LogDao getLogDao() {
    return logDao;
}
public UserDao getUserDao() {
    return userDao;
}

public void setBeanName(String beanName) {
    System.out.println("beanName:"+beanName);        
}

public void initMethod1(){
    System.out.println("initMethod1");
}
public void initMethod2(){
    System.out.println("initMethod2");
}

}

spring中bean配置和bean注入

在①处,我们使用@Service将LogonService标注为一个Bean,在②处,通过@Autowired注入LogDao及UserDao的Bean。@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入到@Autowired标注的变量中。

2.2.2 使用@Autowired的required属性

如果容器中没有一个和标注变量类型匹配的Bean,Spring容器启动时将报NoSuchBeanDefinitionException的异常。如果希望Spring即使找不到匹配的Bean完成注入也不用抛出异常,那么可以使用@Autowired(required=false)进行标注:

@Service public class LogonService implements BeanNameAware{ @Autowired(required=false) private LogDao logDao; ... }

默认情况下,@Autowired的required属性的值为true,即要求一定要找到匹配的Bean,否则将报异常。

2.2.3 使用@Qualifier指定注入Bean的名称

如果容器中有一个以上匹配的Bean时,则可以通过@Qualifier注解限定Bean的名称,如下所示:

spring中bean配置和bean注入

@Service public class LogonService implements BeanNameAware{ @Autowired(required=false) private LogDao logDao; //①注入名为UserDao,类型为UserDao的Bean @Autowired @Qualifier("userDao") private UserDao userDao; }

spring中bean配置和bean注入

这里假设容器有两个类型为UserDao的Bean,一个名为userDao,另一个名为otherUserDao,则①处会注入名为userDao的Bean。

2.2.4 对类方法进行标注

@Autowired可以对类成员变量及方法的入参进行标注,下面我们在类的方法上使用@Autowired注解:

spring中bean配置和bean注入

package com.baobaotao.anno;

import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service;

@Service public class LogonService implements BeanNameAware{

private LogDao logDao;
private UserDao userDao;


@Autowired
public void setLogDao(LogDao logDao) {
    this.logDao = logDao;
}

@Autowired
@Qualifier("userDao")
public void setUserDao(UserDao userDao) {
    System.out.println("auto inject");
    this.userDao = userDao;
}

}

spring中bean配置和bean注入

如果一个方法拥有多个入参,在默认情况下,Spring自动选择匹配入参类型的Bean进行注入。Spring允许对方法入参标注@Qualifier以指定注入Bean的名称,如下所示:

@Autowired public void init(@Qualifier("userDao")UserDao userDao,LogDao logDao){ System.out.println("multi param inject"); this.userDao = userDao; this.logDao =logDao; }

在以上例子中,UserDao的入参注入名为userDao的Bean,而LogDao的入参注入LogDao类型的Bean。

一般情况下,在Spring容器中大部分的Bean都是单实例的,所以我们一般都无须通过@Repository、@Service等注解的value属性为Bean指定名称,也无须使用@Qualifier按名称进行注入。

2.2.5 对标准注解的支持

此外,Spring还支持@Resource和@Inject注解,这两个标准注解和@Autowired注解的功能类型,都是对类变量及方法入参提供自动注入的功能。@Resource要求提供一个Bean名称的属性,如果属性为空,则自动采用标注处的变量名或方法名作为Bean的名称。

spring中bean配置和bean注入

package com.baobaotao.anno;

import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component public class Boss {

private Car car;

public Boss(){
    System.out.println("construct...");
}

// @Autowired // private void setCar(Car car){ // System.out.println("execute in setCar"); // this.car = car; // }

@Resource("car")
private void setCar(Car car){
    System.out.println("execute in setCar");
    this.car = car;
}

@PostConstruct
private void init1(){
    System.out.println("execute in init1");
}

@PostConstruct
private void init2(){
    System.out.println("execute in init1");
}

@PreDestroy
private void destory1(){
    System.out.println("execute in destory1");
}

@PreDestroy
private void destory2(){
    System.out.println("execute in destory2");
}

}

spring中bean配置和bean注入

这时,如果@Resource未指定"car"属性,则也可以根据属性方法得到需要注入的Bean名称。可见@Autowired默认按类型匹配注入Bean,@Resource则按名称匹配注入Bean。而@Inject和@Autowired一样也是按类型匹配注入的Bean的,只不过它没有required属性。可见不管是@Resource还是@Inject注解,其功能都没有@Autowired丰富,因此除非必须,大可不必在乎这两个注解。(类似于Xml中使用或者进行注入,如果使用了@Autowired或者Resource等,这不需要在定义Bean时使用属性注入和构造方法注入了)

2.2.6 关于Autowired和@Resource

1.@Autowired注入是按照类型注入的,只要配置文件中的bean类型和需要的bean类型是一致的,这时候注入就没问题。但是如果相同类型的bean不止一个,此时注入就会出现问题,Spring容器无法启动。 
2.@Resourced标签是按照bean的名字来进行注入的,如果我们没有在使用@Resource时指定bean的名字,同时Spring容器中又没有该名字的bean,这时候@Resource就会退化为@Autowired即按照类型注入,这样就有可能违背了使用@Resource的初衷。所以建议在使用@Resource时都显示指定一下bean的名字@Resource(name="xxx") 

2.2.7 让@Resource和@Autowired生效的几种方式

1.在xml配置文件中显式指定 

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />   
  
<!-- 为了使用@Resource标签,这里必须配置一个后置处理器 -->  
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

2.在xml配置文件中使用context:annotation-config 

<context:annotation-config />

3.在xml配置文件中使用context:component-scan 

<context:component-scan base-package="com.baobaotao.anno"/>

4.重写Spring容器的Context,在自定义BeanFactory时调用AnnotationConfigUtils.registerAnnotationConfigProcessors()把这两个注解处理器增加到容器中。 

一开始使用公司框架的时候发现可以在web层使用@Resource以及@Autowired来注入一些bean,首先这个注解是Spring提供的,自己把这部分代码抽出来写了小例子,发现要想使用Spring的这两注解,必须直接或者间接的引入AutowiredAnnotationBeanPostProcesso以及CommonAnnotationBeanPostProcessor这两个注解处理器引入到BeanDefinitions中,否则不会实现注入的,但是仔细阅读公司框架代码后发现没有地方直接或间接引入这两个注解处理器,发现一个细节,公司框架所依赖的Spring版本是2.5.6而我使用的Spring版本是2.5.5,当初的结论是高版本的Spring在容器启动的时候,自动把这两个注解处理器加入到BeanDefinitions中,这几天仔细看了看Spring的源代码,发现Spring2.5.6并没有这样做。然后子写DEBUG了一下公司框架的源代码,最后发现原来公司框架有一个自己的XmlWebApplicationContext,在这个context中重写customizeBeanFactory(),在这个方法中调用了AnnotationConfigUtils.registerAnnotationConfigProcessors()方法把这两自动注解处理器加入到BeanDefinitions中,这样公司框架在web层就支持@Resource和@Autowired进行自动注入啦 

spring中bean配置和bean注入

// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) //

package com.alibaba.citrus.springext.support.context;

import com.alibaba.citrus.springext.ResourceLoadingExtendable; import com.alibaba.citrus.springext.ResourceLoadingExtender; import com.alibaba.citrus.springext.support.context.InheritableListableBeanFactory; import com.alibaba.citrus.springext.support.resolver.XmlBeanDefinitionReaderProcessor; import java.io.IOException; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.core.io.Resource; import org.springframework.core.io.support.ResourcePatternResolver;

public class XmlWebApplicationContext extends org.springframework.web.context.support.XmlWebApplicationContext implements ResourceLoadingExtendable { private ResourceLoadingExtender resourceLoadingExtender; private boolean parentResolvableDependenciesAccessible = true;

public XmlWebApplicationContext() {
}

public boolean isParentResolvableDependenciesAccessible() {
    return this.parentResolvableDependenciesAccessible;
}

public void setParentResolvableDependenciesAccessible(boolean parentResolvableDependenciesAccessible) {
    this.parentResolvableDependenciesAccessible = parentResolvableDependenciesAccessible;
}

public void setResourceLoadingExtender(ResourceLoadingExtender resourceLoadingExtender) {
    if(this.resourceLoadingExtender != null) {
        this.getApplicationListeners().remove(this.resourceLoadingExtender);
    }

    this.resourceLoadingExtender = resourceLoadingExtender;
    if(resourceLoadingExtender instanceof ApplicationListener) {
        this.addApplicationListener((ApplicationListener)resourceLoadingExtender);
    }

}

protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
    (new XmlBeanDefinitionReaderProcessor(beanDefinitionReader)).addConfigurationPointsSupport();
}

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    super.customizeBeanFactory(beanFactory);

    //AnnotationConfigUtils.registerAnnotationConfigProcessors()方法把这两自动注解处理器加入到BeanDefinitions中,这样公司框架在web层就支持@Resource和@Autowired进行自动注入 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory, (Object)null); }

protected DefaultListableBeanFactory createBeanFactory() {
    return (DefaultListableBeanFactory)(this.isParentResolvableDependenciesAccessible()?new InheritableListableBeanFactory(this.getInternalParentBeanFactory()):super.createBeanFactory());
}

protected Resource getResourceByPath(String path) {
    Resource resource = null;
    if(this.resourceLoadingExtender != null) {
        resource = this.resourceLoadingExtender.getResourceByPath(path);
    }

    if(resource == null) {
        resource = super.getResourceByPath(path);
    }

    return resource;
}

protected ResourcePatternResolver getResourcePatternResolver() {
    final ResourcePatternResolver defaultResolver = super.getResourcePatternResolver();
    return new ResourcePatternResolver() {
        public Resource\[\] getResources(String locationPattern) throws IOException {
            ResourcePatternResolver resolver = null;
            if(XmlWebApplicationContext.this.resourceLoadingExtender != null) {
                resolver = XmlWebApplicationContext.this.resourceLoadingExtender.getResourcePatternResolver();
            }

            if(resolver == null) {
                resolver = defaultResolver;
            }

            return resolver.getResources(locationPattern);
        }

        public ClassLoader getClassLoader() {
            return defaultResolver.getClassLoader();
        }

        public Resource getResource(String location) {
            return defaultResolver.getResource(location);
        }
    };
}

}

spring中bean配置和bean注入

点赞
收藏
评论区
推荐文章
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 )
Easter79 Easter79
3年前
Spring容器初始化过程
一、Spring容器高层视图Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配号Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。!(http://images2015.cnblogs.com/blog/5
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Easter79 Easter79
3年前
Spring高级应用之注入嵌套Bean
在Spring中,如果某个Bean所依赖的Bean不想被Spring容器直接访问,可以使用嵌套Bean。和普通的Bean一样,使用<bean元素来定义嵌套的Bean,嵌套Bean只对它的外部的Bean有效,Spring容器无法直接访问嵌套的Bean,因此定义嵌套Bean也无需指定id属性。如下配置片段是一个嵌套Bean的示例:<bean id
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