Spring自动装配

为了减少XML的配置数量。Spring提供了几种技巧来解决这一问题:

自动装配(autowiring): 有助于减少<property>元素和<constroctor-arg>元素,让Spring自动识别如何装配Bean的依赖关系

自动检测(autodiscovery): 让Spring自动识别那些类需要被配置成Spring Bean,从而减少对<bean>元素的使用

<!--more-->

自动装配Bean属性

4种类型的自动装配

  • byName: 把与Bean的属性具有相同名字(或ID)的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的名字相匹配的Bean,该属性不进行装配。

  • byType: 把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。若没有相匹配的Bean,则不装配。

  • constructor: 把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean的构造器的对应入参中。

  • autodetect: 首先尝试用constructor进行自动装配,若失败就再次尝试用byType进行自动装配。

byName自动装配

通过byName元素Spring可以实现自动查找其他Bean中是否有相同的属性名称,有则进行装配。体会下面的案例:

EmpService.java

package demo2;
public class EmpService {    //注入Dao
    private EmpDao empDao;
    public void setEmpDao(EmpDao empDao) {        System.out.println("EmpService --> EmpDao");
        this.empDao = empDao;
    }
}

EmpDao.java

package demo2;
public class EmpDao {}

spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="empService" class="demo2.EmpService" autowire="byName"/>
    <bean id="empDao" class="demo2.EmpDao"/>
</beans>

Test测试类

@Test
public void run(){    //加载Spring上下文
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
    ac.getBean("empService");
}

打印结果:

情况一:如果通过之前的方式通过ref来注入一个引用Bean呢?我们改变上述spring.xml中的代码:

<bean id="empDao" class="demo2.EmpDao"/>
<bean id="empService" class="demo2.empService">
    <property name="empDao" ref="empDao"/>
</bean>

结果和上述相同。

情况二:如果我们改变EmpService.javaempDao的数据类型

package demo2;
public class EmpService {    //注入Dao
    private String empDao;
    public void setEmpDao(String empDao) {        System.out.println("EmpService --> EmpDao");
        this.empDao = empDao;
    }
}

打印结果:

观察发现autowire="byName"自动装配的含义就是:

​ 若BeanA中存在与BeanB的idid="empDao"相同的属性(且存在setter方法)private EmpDao empDao;Spring就能自动进行装配。

​ 那么,开始我一直疑惑这个byName注入不是查找的bean名称和另一个bean的属性名称相同就能注入吗,其实并不是。首先我们要明白注入是注入另一个类或接口什么的,Spring让这两个bean之间产生了联系,即我们定义一个普通类型的参数private String empDao,即使名称和另一个Bean相同empDao,但是它只是一个属性,怎么能让一个普通的参数注入到另一个Bean中呢?(注意这里我是在自动注入的前提下说的,当然是可以实现注入的)。

缺点: byName的缺点就是首先要存在这个和另一个Bean的id相同的属性,其次,如果多个Bean中都存在这个属性,那Spring都会将这些Bean装配进去。如下案例:

新创建一个UserDao.java

package demo2;
public class EmpDao {}

EmpService.java

package demo2;
public class EmpService {    //注入Dao
    private EmpDao empDao;
    public void setEmpDao(EmpDao empDao) {        System.out.println("EmpService --> EmpDao");
        this.empDao = empDao;
    }
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {        System.out.println("EmpService --> UserDao");
        this.userDao = userDao;
    }
}

spring.xml中注入该Bean:

<bean id="userDao" class="demo2.UserDao"/>

观察结果:

如上就体现了这中注入方法的缺陷,就是如果多个Bean的id名称都和另一个bean的属性有相同的,那么Spring会全部注入。

byType自动装配

byType自动装配的方法和byName装配方式类似,区别在于byType找的是相同的数据类型,而byName找的是相同的名称

EmpService.java

package demo2;
public class EmpService {    //注入Dao
    private EmpDao emp;
    public void setEmpDao(EmpDao emp) {        System.out.println("EmpService --> EmpDao");
        this.emp = emp;
    }
}

spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="empService" class="demo2.EmpService" autowire="byType"/>
    <bean id="empDao" class="demo2.EmpDao"/>
</beans>

Test测试类

@Test
public void run(){    //加载Spring上下文
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
    ac.getBean("empService");
}

打印结果:

观察:上面EmpDaobean的id是empDao,但EmpService中存在的属性是private EmpDao emp;,注意不是empDao,那么当我们配置了autowire="byType"后,因为数据类型相同,Spring仍可将EmpDao注入到EmpService中。

缺点

​ 如果Spring找到了多个Bean的,他们的类型与需要自动装配的属性的类型都匹配,那么Spring会抛出异常,而不是选择注入哪个。如下情况:

其他不变,我们在spring.xml增加一行配置:

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="empService" class="demo2.EmpService" autowire="byType"/>
    <bean id="empDao" class="demo2.EmpDao"/>
    <bean id="dao" class="demo2.EmpDao"/>
</beans>

打印结果:

可以看到,当我们在spring.xml中注入两个类型相同的Bean(当然名称不能相同),此时就会报错。

为解决这一错误,Spring提供了pimaryautowire-candidate两个属性。

  • 为自动装配标识一个首选Bean,使用primary属性,如果设置primary="true"那么该Bean会被优先选择。但Spring却给每一个<bean>默认都配置了primary="true"属性,也就是此时每个Bean都是首选的,而你想指定哪个Bean是首选就必须设置其他Bean都是primary="false"候选。所以说:primary属性仅对标识的首选Bean有意义。如果想解决上面多个Bean都符合情况造成的报错,必须引入下面属性:

  • 即为想被忽略注入的<bean>配置autowire-candidate="false"属性,这样Spring在进行装配时就会忽略autowire-candidate="false"标识的Bean。

spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="empService" class="demo2.EmpService" autowire="byType"/>
    <bean id="empDao" class="demo2.EmpDao"/>
    <bean id="dao" class="demo2.EmpDao" autowire-candidate="false"/>
</beans>

constructor自动装配

如果要通过构造器来装配Bean,那我们可以移除<constructor-arg>元素,采用Spring自动注入的方式:(注意这里我们改变了以上的代码逻辑,增加了一个Emp接口,让EmpDaoUserDao都继承这个接口)

Emp.java

package demo2;
public interface Emp {}

EmpDao.java

package demo2;
public class EmpDao implements Emp {}

UserDao.java

package demo2;
public class UserDao implements Emp {}

EmpService.java

package demo2;
public class EmpService {    private Emp emp;
    public void setEmp(Emp emp) {        System.out.println("执行...");
        this.emp = emp;
    }
    public EmpService(Emp emp) {        System.out.println("这是构造参数...");
        this.emp = emp;
    }
}

同时这种方式也存在和byType一样的缺点:

spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="empService" class="demo2.EmpService" autowire="constructor"/>
    <bean id="empDao" class="demo2.EmpDao"/>
    <bean id="userDao" class="demo2.UserDao"/>
</beans>

结果仍报错:

最佳自动装配—>由Spring决定怎么装配

<bean id="empService" class="demo2.EmpService" autowire="autodetect"/>

默认自动装配

<beans ....
    default-autowire="xxx"
>

使用注解自动装配

从Spring2.5开始可以使用注解实现自动装配,注解装配和使用XML中的autowire本身没有太大区别,但是注解装配可以实现更小颗粒度的装配。但是Spring默认是禁用注解装配的,所以我们首先要在spring.xml中启用注解装配。最简单的方式就是启用Spring的context命名空间配置中的<context:annotation-config>元素,如下:

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config/>
</beans>

Spring3支持几种不同的自动装配注解:

  • Spring自带的@Autowired注解

  • JSR-330的@Inject注解

  • JSR-250的@Resource注解

使用@Autowired

如下案例:

spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd">
​
    <context:annotation-config/>
    <bean id="empService" class="demo2.EmpService"/>
    <bean id="empDao" class="demo2.EmpDao"/>
</beans>

EmpService.java

package demo2;
import org.springframework.beans.factory.annotation.Autowired;
public class EmpService {    private Emp emp;
    @Autowired
    public void setEmp(Emp emp) {        System.out.println("执行...");
        this.emp = emp;
    }
    public void play(){        emp.play();
    }
}

Emp.java

package demo2;
public interface Emp {    void play();
}

EmpDao.java

package demo2;
public class EmpDao implements Emp {    public void play() {        System.out.println("EmpDao: play...");
    }
}

Test测试类

@Test
public void run(){    //加载Spring上下文
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
    EmpService es = (EmpService) ac.getBean("empService");
    es.play();
}

除了上面标记在setter方法上,还可以直接标记到私有属性上:

package demo2;
import org.springframework.beans.factory.annotation.Autowired;
public class EmpService {    @Autowired
    private Emp emp;
    public void setEmp(Emp emp) {        System.out.println("执行...");
        this.emp = emp;
    }
    public void play(){        emp.play();
    }
}

可以看到,使用这种方式仍可以完成注入,并且我们发现将@Autowired直接标记到私有属性上,并不会执行setter方法,但是仍完成了注入,这其实就是@Autowired的一大优势,它简化了setter方法的书写,采用Java的反射机制完成的注入。

缺点:采用@Autowired注解注入固然方便,但是也存在缺点,即被标注的属性或参数必须是可注入的,如下列情况,我们将emp的数据类型改变(注意这里要注释掉play方法,因为数据类型改变了也就不能再调用play方法):

package demo2;
import org.springframework.beans.factory.annotation.Autowired;
public class EmpService {    @Autowired
//    private Emp emp;
    private String emp;
    /*public void play(){        emp.play();
    }*/
}

此时就会报错NoSuchBeanDefinitionException,因为我们认为属性不一定要被装配,返回null值也好,从而避免抛出异常,那么我们就可以在@Autowired中添加required属性,表示是否一定要进行装配:

package demo2;
import org.springframework.beans.factory.annotation.Autowired;
public class EmpService {    @Autowired(required = false)
//    private Emp emp;
    private String emp;
    /*public void play(){        emp.play();
    }*/
}

这样就不会再出现保报错的情况。

注意: required属性可以用于@Autowired注解所使用的任意地方,但当使用构造器进行装配时,只有一个构造器可以将@Autowiredrequired属性设置为true,其他都必须设置为required=false。此外,使用@Autowired标记多个构造器时,Spring会从所有瞒住装配条件的构造器中选择入参最多的构造器。

限定歧义性的依赖

对于出现多个Bean满足注入条件的解决,上面也介绍了一系列的方法,即使是上面的@Autowired细颗粒度的注入方式仍然无法解决多个Bean满足注入条件的情况,所以Spring提供了一个更好的方式解决这一问题:

使用@Qualifier("beanName")限定注入哪个Bean

spring.xml

<bean id="empService" class="demo2.EmpService"/>
    <bean id="empDao" class="demo2.EmpDao"/>
    <bean id="userDao" class="demo2.UserDao"/>

此时,因为EmpDaoUserDao都实现了Emp接口,所以empDaouserDao两个Bean都瞒住注入条件,此时就会产生NoSuchBeanDefinitionException的错误。

EmpService.java

package demo2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class EmpService {    @Autowired(required = false)
    @Qualifier("empDao")
    private Emp emp;
    public void play(){        emp.play();
    }
}

即这里我们限定了将empDao注入,而不是注入userDao,这样就会避免出现错误。

@Inject基于标准的自动装配

为了统一各种依赖注入框架编程模型,JCP(Java Community Process)发布了一套Java的依赖注入规范,@Inject注解则是其核心部件,该注解和@Autowired几乎相同,但对于一些特殊情况,@Inject也有自己的处理办法:

  1. 首先@Inject没有required属性,所以被标记的属性必须是可注入的

    1. 歧义性的Bean定义:@Qualifier —> @Named

在注解注入中使用表达式

@Value

自动检测Bean

当在Spring配置中增加了<context:annotation-config>时,我们希望Spring特殊对待我们所定义的Bean里的某一组注解,并使用这些注解指导Bean的装配,由此产生了 <context:component-scan元素。它能大大简化对<bean>的配置,通过在<context:component-scan>元素中指定要扫描指定包下的Bean对象,如:

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:component-scan base-package="demo2"/>
</beans>

那么<context:component-scan>又是如何知道哪些类需要注册为Spring Bean呢?

为自动检测标注Bean

<context:component-scan>会查找使用构造型(stereotype)注解所标注的类

@Component —>通用的构造性注解,标识该类为Spring组件。

@Controller —>标识将该类定义为Spring MVC controller

@Repository —>标识将该类定义为数据仓库

@Service —>标识将该类定义为服务

使用@Component标注的任意自定义注解

举例:

spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:component-scan base-package="demo2"/>
</beans>

如上我们只需要开启注解支持.

EmpService.java

package demo2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EmpService {    @Autowired(required = false)
    private Emp emp;
    @Bean
    public EmpDao empDao(){        return new EmpDao(userDao());
    }
    public void play(){        emp.play();
    }
}

如上,我们首先使用@Configuration标记的Java类,就等价于XML配置中的<beans>元素。使用@Bean就等价于<bean>元素,(@Bean告知Spring这个方法将返回一个对象,该对象应该被注册为Spring应用上下文中的一个Bean。方法名将作为该Bean的ID。在该方法中所实现的所有逻辑本质上都是为了创建Bean)这样我们就实现了将一个JavaBean对象交付给Spring管理,再添加@Autowired就完成了自动注入的功能。这是注入一个简单对象,那么我们怎么注入一个引用呢?

package demo2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EmpService {    @Qualifier("empDao")
    @Autowired(required = false)
    private Emp emp;
    @Bean
    public UserDao userDao(){        return new UserDao();
    }
    @Bean
    public EmpDao empDao(){        return new EmpDao(userDao());
    }
}

向另一个Bean中注入一个引用,只需要在此Bean的返回值中调用另外一个被@Bean标记的方法名即可完成注入,但是仍要考虑歧义性问题(使用@Qualifier进行限定)

总结

综上:我们已经介绍了Spring自动装配和注解开发的相关知识,下面我们来回顾一下。

自动装配

  • byName: 把与Bean的属性(在JavaBean中定义的属性)和具有相同名字(ID)的其他Bean自动装配到Bean的对应属性中。

  • byType: 把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。

  • constructor: 把与Bean的构造器参数入参具有相同类型的其他Bean自动装配到Bean的对应入参中。

  • autodetect: 首先舱室使用constructor进行自动装配,如果装配失败再尝试使用byType进行装配。

注解开发

自动装配提供的注解:

​ @Autowired — required=false — @Qualifier("beanName")

​ @Inject — @Named

Spring基于Java的注解开发:

​ @Configuration( <beans>

​ @Bean( <bean>

注意问题:

  1. 以上的自动装配的方式都无法避免多个Bean同时满足注入条件的情况,但是Spring针对不同的注入方式提供了不同的解决办法:

    • byName会对满足条件的Bean都进行封装,不加考虑。

    • byType对遇到多个满足注入条件的Bean时会抛出异常,同时给出primary(仅对首选Bean有意义)、autowire-candidate="false"(忽略某个Bean的自动装配)。(注:我们要明白Spring默认将所有Bean都设置为primary="true"这样就没有什么首选Bean可言。所以此时我们最好采用autowire-candidate忽略某个Bean的自动装配。

    • constructor自动装配和byType有一样的局限性,会报错。

    • 综合以上,提出了最佳的自动装配方式:autowire="autodetect"。Spring首先会尝试使用constructor自动装配,如果没有与构造器相匹配的Bean,Spring将尝试使用byType自动装配。

      1. 注解开发有常用的三个自动装配方式:1.@Autowired(Spring自带的注解); 2.Inject(基于标准的自动装配);3.@Resource

    • @Autowired(默认按照类型装配)

      1. 避免@Autowired标注的属性或参数是不可装配的,提供required=false属性。

      2. 限定歧义性的依赖(多个Bean的情况),提供@Qualifier("beanName")缩小选择范围,指定某一个Bean

    • @Inject注解自动装配和@Autowired注解相似,但是对上述解决方案给出的注解不同,如以下:

      1. @Inject限定所标记的属性必须是可装配的,不然就会报错

      2. @Qualifier —> @Named

    • @Resource(默认按照名称装配)

      是jdk1.6支持的注解

<br/>

交流

如果大家有兴趣,欢迎大家加入我的Java交流群:671017003 ,一起交流学习Java技术。博主目前一直在自学JAVA中,技术有限,如果可以,会尽力给大家提供一些帮助,或是一些学习方法,当然群里的大佬都会积极给新手答疑的。所以,别犹豫,快来加入我们吧!

<br/>

联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

  • Blog@TyCoding's blog

  • GitHub@TyCoding

  • ZhiHu@TyCoding

(二)Spring自动装配相关推荐

  1. 一步一步手绘Spring DI运行时序图(Spring 自动装配之依赖注入)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  2. SpringBoot源码分析(二)之自动装配demo

    SpringBoot源码分析(二)之自动装配demo 文章目录 SpringBoot源码分析(二)之自动装配demo 前言 一.创建RedissonTemplate的Maven服务 二.创建测试服务 ...

  3. Spring 自动装配详细讲解

    一.什么是自动装配 1.自动装配是使用spring满足bean依赖的一种方法 2.spring会在应用上下文中为某个bean寻找其依赖的bean. 二.自动装配的方法有哪些 1.在xml中显式配置: ...

  4. Spring 自动装配 ‘byType’

    转载自   Spring 自动装配 'byType' Spring 自动装配 'byType' 这种模式由属性类型指定自动装配.Spring 容器看作 beans,在 XML 配置文件中 beans ...

  5. Spring 自动装配 ‘byName’

    转载自  Spring 自动装配 'byName' Spring 自动装配 'byName' 这种模式由属性名称指定自动装配.Spring 容器看作 beans,在 XML 配置文件中 beans 的 ...

  6. spring自动装配依赖包_解决Spring自动装配中的循环依赖

    spring自动装配依赖包 我认为这篇文章是在企业应用程序开发中使用Spring的最佳实践. 使用Spring编写企业Web应用程序时,服务层中的服务量可能会增加. 服务层中的每个服务可能会消耗其他服 ...

  7. Java的注解机制——Spring自动装配的实现原理

    JDK1.5加入了对注解机制的支持,实际上我学习Java的时候就已经使用JDK1.6了,而且除了@Override和@SuppressWarnings(后者还是IDE给生成的--)之外没接触过其他的. ...

  8. Spring自动装配----注解装配----Spring自带的@Autowired注解

    Spring自动装配----注解装配----Spring自带的@Autowired注解 父类 package cn.ychx;public interface Person {public void ...

  9. spring自动装配、注解

    spring自动装配 Spring 自动装配 byName 这种模式由属性名称指定自动装配.Spring 容器看作 beans,在 XML 配置文件中 beans 的 auto-wire 属性设置为 ...

最新文章

  1. 型人格 disc测试_3号,成就型人格的专业和职业选择@九型人格测试
  2. 常见机器学习算法背后的数学
  3. 《按键消抖与LED控制》实验的个人思考与总结
  4. android 获取短信验证码倒计时
  5. flume1.8 开发指南学习感悟
  6. nodejs启动机制分析
  7. 微软大数据_我对Microsoft的数据科学采访
  8. 一步步编写操作系统 46 用c语言编写内核3
  9. html区块位置怎么设置,HTML 区块
  10. 使用MEF方便的扩展
  11. Memcached 一致性哈希算法PHP实现
  12. 面对互联网上的汩汩恶意,如何构建反欺诈体系?
  13. python程序的扩展名是perl程序的扩展名是_Python 程序扩展名(py, pyc, pyw, pyo, pyd)及发布程序时的选择...
  14. html图片浮空但占位置,求助:鼠标经过图片时,图片悬浮出现变大
  15. 深入理解viewport及相关属性的关系
  16. android模拟器定位失败,Android-无法在模拟器上获取GPS位置
  17. C语言将字符串转换为数字
  18. 什么是360度全景图,360度全景图有什么用
  19. 身为IT人你应该知道的几个威客网站【转】
  20. 法大大登榜《胡润中国瞪羚企业》

热门文章

  1. Ubuntu 16.04 安装pyk4a
  2. 做完系统回来计算机连接不上网络,电脑重装系统后网络连接不上怎么处理
  3. 4K超高清电视全面支持HDMI技术
  4. JavaBean技术的使用
  5. 事业单位面试题 一(自我练习及答案)
  6. Field tagService in xxx.service.impl.ArticleServiceImpl required a bean of type ‘xxserviceTagService
  7. 复合类型(compound type)
  8. 数字图像处理 -灰度变换 之 对数变换(Log Transformation)
  9. oracle时间戳表达式,Oracle Timestamp类型
  10. mqtt broker(代理/服务器)mosquitto的安装 配置 使用