Spring Bean常用的的装配方式详解

Bean常用的装配方式有3种:

  • 基于xml的装配
  • 基于Annotation(注解)的装配
  • 基于Java配置类的装配

基于xml的装配

在xml文件中配置Bean。

如果依赖很多,xml配置文件会很臃肿,后期维护、升级不方便。自动装配可解决这一问题。

基于xml的自动装配

在<bean>中使用autowired属性完成依赖的自动装配,不再使用<property>手动注入setter方法中的依赖,简化了配置,减少了xml中的代码量。

autowire属性的属性值:

  • no 不使用自动装配。缺省autowire属性时默认值就是no。
  • byName 根据setter方法的名称来自动装配
  • byType 根据所依来的类型(Bean)来自动装配
  • constructor 根据构造函数的形参表的数据类型进行byType方式的自动装配
  • default 全局自动装配

1、byName

示例:

class Student{
  private String name;
  public Student(String name){
    this.name=name;
  }
  public String getName(){
    return name;
  }
}
class Teacher{
  private Student student;

  public void setStudent(Student student) {
    this.student = student;
  }
  public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}

Teacher依赖于Student,依赖的对象要写成成员变量的形式。如果要使用自动装配,依赖对象的注入只能使用setter方式。

byName,name指的是setXxx()注入依赖的那个xxx,比如setStudent(Student student),name指的是student,将set后面的部分提出来,变成Camel写法。name不是指形参名的student。

xml中的配置:

  <bean id="student" class="my_package.Student">
<constructor-arg value="张三" />
</bean>
<bean id="teacher" class="my_package.Teacher" autowire="byName" />

第一个Bean是基于xml的普通装配,第二个Bean的配置是byName形式的自动装配。

byName自动装配的执行过程:在这个Bean的定义中,找到setter方法,这里是setStudent(),其name是student(set后面部分提出来,变成Camel写法),根据这个name(student)找打到id/name是student的Bean实例,将这个实例自动注入。

所以对<bean>的id/name、setter方法的命名有严格要求。

原本是要用<property name ref="" />子元素注入依赖的,如果依赖较多,会写一大堆<property>子元素。自动装配,不管这个一Bean有多少个依赖,一句代码搞定,减少了代码量,由Spring容器自动注入依赖。但Spring容器要做更多的工作,装配速度会变慢。

说明:自动装配只能完成setter形式的依赖注入,不能完成构造器方式的依赖注入,且只能注入其它Bean,不能注入String、数组、集合等Java自带的类型。

测试代码:

public class Test {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
    teacher.say();
  }
}

运行,控制台打印出"张三,叫家长来一下。"。

2、byType

根据要注入的Bean的类型来自动装配。

在上面的例子中,setStudent(Student student),要注入的依赖是Student类型的实例。

byType自动装配的执行过程:在这个Bean的定义中,找到setter方法,找到setter方法要注入的Bean的类型(Student),在Spring容器中找到Student类型的实例,注入。

如果Spring容器中该依赖有多个配置,比如:

<bean id="student" class="my_package.Student">
    <constructor-arg value="张三" />
  </bean>
  <bean id="student1" class="my_package.Student">
    <constructor-arg value="李四" />
  </bean>

它们都是Student这个Bean的配置,Spring容器不知道要注入的依赖是哪一个,会报错,所以依赖的bean只能有一个配置。

这种是可以的:

  <bean id="student" class="my_package.Student" scope="prototype">
<constructor-arg value="张三" />
</bean>

虽然Spring容器中可能有这个Bean的多个实例,但这些实例是一样的。

示例:

将byName示例中的xml中的配置修改如下即可

  <bean id="student" class="my_package.Student">
<constructor-arg value="张三" />
</bean>
<bean id="teacher" class="my_package.Teacher" autowire="byType" />

3、constructor

class Student{
  public String getName(){
    return "张三";
  }
}
class Teacher{
  private Student student;
  public Teacher(Student student){
    this.student=student;
  }
  public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}

需要用构造器注入依赖,Spring容器会自动根据构造器中参数类型,用byType方式注入对应类型的依赖。

只能有一个构造器,否则Spring容器不知道使用哪个构造器。

xml中的配置:

<bean id="student" class="my_package.Student" />
<bean id="teacher" class="my_package.Teacher" autowire="constructor" />

4、default

<?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"
    default-autowire="byName">
  <bean id="student" class="my_package.Student">
    <constructor-arg value="张三" />
  </bean>
  <bean id="teacher" class="my_package.Teacher" autowire="default" />

在<beans>中设置默认的自动装配方式,在需要使用自动装配的<bean>指定autowire="default",这样该<bean>使用的自动装配方式就是<beans>中设置的默认方式。

统一了应用的自动装配方式。

基于注解的装配

基于xml装配的方式,如果<bean>很多,xml文件依然很臃肿。基于注解的装配解决了这一问题。

基于注解的装配是最常用的。

Spring常用的注解:

  • @Autowired 按类型自动装配(byType)。
  • @Qualifier 按名称自动装配,不能单用,需要和@Autowired配合使用(byName)。
  • @Resource 是byName、byType方式的结合。

记法:Autowired——Type,Qualifier——Name,ATQN。

示例 @Autowired

class Student{
  private String name;
  public Student(String name){
    this.name=name;
  }
  public String getName(){
    return name;
  }
}
class Teacher{
  @Autowired
  private Student student;
  public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}

不必写setter方法,也不必写构造器。在依赖的对象上添加@Autowired注解(当然也可以在setter方法上写),即按照类型自动装配依赖。

上面在Student类型的依赖上添加了@Autowired注解,会自动在Spring容器中,找到Student类型的Bean,注入。相当于byType。

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 https://www.springframework.org/schema/context/spring-context.xsd">  <context:annotation-config />
  <bean id="student" class="my_package.Student">
    <constructor-arg value="张三" />
  </bean>
  <bean id="teacher" class="my_package.Teacher"/>
</beans>

基于注解的装配都需要用<context:annotation-config />开启注解装配,这句代码是告诉Spring容器,下面的这些bean使用的是注解装配。

<bean>中不使用autowire属性。

测试:

public class Test {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
    Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
    teacher.say();
  }
}

可以看到控制台打印出"张三,叫家长来一下。"。

示例 @Qualifier

修改Teacher类代码如下,其余不变。

class Teacher{
  @Autowired
  @Qualifier(value="student")
  private Student student;
  public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}

在依赖的Bean实例上添加@Qualifier,@Qualifier不能单独用,还需要添加@Autowired。

@Qualifier是byName方式的自动装配,需要用value指定依赖Bean的id/name,Spring容器根据这个value找到id/name为vBean,注入。

可简写为@Qualifier("student")。

示例 @Resource

class Teacher{
  @Resource(name = "student")
  private Student student;
  public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}

先根据name找到Spring容器中name/id为student的Bean,注入。即优先以getName方式。

如果找不到name/id为指定值的Bean,或缺省name直接写@Resource,则以默认的getName方式:写在字段上默认name为成员变量名(student),写在setter方法上默认为set后面部分得Camel写法,比如setStudent()默认name为student。

如果还是找不到依赖的Bean,则以byType方式注入。

说明

  • 以上注解写在字段上、setter方法上均可,都是注入一个依赖。
  • Spring提供了@Resource注解,但此注解需要第三方包javax.annotation-api.jar的支持。如果用Maven,会自动添加Spring依赖的第三方包,比如commons-logging.jar、javax.annotation.jar,如果是自己添加Spring的jar库,则还需要手动添加Spring依赖的第三方jar包。
  • 需要在xml中用<context:annotation-config />开启注解。

Spring常用的其它注解

  • @Service 将业务层(Service层)的类标识为Spring容器中的Bean
  • @Controller 将控制层的类标识为Spring容器中的Bean
  • @Repository 将数据访问层(Dao层)的类标识为Spring容器中的Bean
  • @Component 将一个类标识为Spring容器中的Bean,相当于具有以上3个注解的功能。但一般都使用专门的,就是说通常使用上面3个注解,很少使用@Component。

前3个是专用的,第四个是通用的。这些注解都只能在类(Bean)上使用。

示例

@Service
class Student{
  public String getName(){
    return "张三";
  }
}
@Service
class Teacher{
  @Resource(name = "student")
  private Student student;
  public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}

xml中的配置:

<context:component-scan base-package="my_package" />
<bean id="student" class="my_package.Student" /> 

需要使用 <context:component-scan base-package="" />指定要扫描的包,这样会Spring容器会自动扫描指定的包,如果包中有上面4个注解,就将之装配为Bean。

<context:component-scan base-package="" />会自动开启注解,所以不必再写<context:annotataion-config />。

其实上面4个注解的作用相当于<bean class="" />。

标注了这4个注解的类,Spring会自动在xml中把这个类配置为Bean,就是说在xml中不必写<bean class="" />。

但只能是<bean class="" />这样基础的配置,如果要<constructor-arg>、<property>传递Java自带类型的参数,或其他Bean必须使用这个Bean的id/name(这个Bean要配置id/name),就不能省略该Bean的配置。

上面的例子中,Teacher类缺省了<bean class="my_package.Teacher" />。

@Resource(name = "student")
private Student student;

Teacher类要用到Student类的id/name,所以Student类写了配置。

其实不写Student类的配置,则会使用byType方式向Teacher注入依赖,也可以。

<context:component-scan base-package="my_package" />这句代码不能缺省。

自动装配简化了配置,减少了代码量,但需要Spring容器做更多的工作,所以创建Bean的速度要慢一些。

基于Java配置类的装配

不使用xml文件配置Bean,而是单独写一个类来配置Bean。

class Student{
  private String name;
  public Student(String name){
    this.name=name;
  }
    public String getName(){
    return name;
  }
}
class Teacher{
  private Student student;
  public Teacher(Student student){
    this.student=student;
  }
    public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}
@Configuration  //表示这个类是用来配置Bean的
class Config{
  @Value("张三") String name;  //创建一个成员变量,相当于String name="张三";
  @Bean(name = "student")  //配置一个Bean,相当于xml中的一个<bean>
  public Student student(){
    Student student=new Student(name);  //创建并返回Bean的实例。
    return student;
  }
  @Bean(name = "teacher")
  public Teacher teacher(){
    return new Teacher(student()); //创建并返回Bean的实例,因为写了构造器,所以可以直接构造器注入依赖。可直接调用本类中的其它方法创建依赖的实例,注入。
  }
}
public class Test {
  public static void main(String[] args) {
    ApplicationContext applicationContext=new AnnotationConfigApplicationContext(Config.class); //注意,和xml配置不同。参数是配置类。
    Teacher teacher=applicationContext.getBean("teacher",Teacher.class);
    teacher.say();
  }
}

上面的例子是通过构造器初始化Bean,也可以写setter方法,通过setter方法初始化Bean:

class Student{
  private String name;
  public void setName(String name){
    this.name=name;
  }
  public String getName(){
    return name;
  }
}
class Teacher{
  private Student student;
  public void setStudent(Student student){
    this.student=student;
  }
  public void say(){
    System.out.println(student.getName()+",叫家长来一下。");
  }
}
@Configuration
class Config{
  @Value("张三") String name;
  @Bean(name = "student")
  public Student student(){
    Student student=new Student();
    student.setName(name);
    return student;
  }
  @Bean(name = "teacher")
  public Teacher teacher(){
    Teacher teacher=new Teacher();
    teacher.setStudent(student());
    return teacher;
  }
}

基于Java配置类的装配,会将Bean的配置耦合到应用代码中,不推荐使用。基于Java配置类的注解还有其它的,此处不再介绍。

使用xml文件配置Bean,是为了解耦,但随着Bean的增多,xml文件越来越臃肿,所以一般是折中使用注解+xml文件的方式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Spring学习之Bean的装配多种方法

    我最近在研究Spring框架的路上,那么今天也算个学习笔记吧!学习一下如何实现Bean的装配方法 Bean的简介 Java开发者一般会听过JavaBean这个概念,所谓的JavaBean,其实就是符合sun规范的一种普通的Java对象,这种对象需要有一个空构造器,为属性添加set/get方法等,之所以这么设计,是为了方便使用反射技术对其进行操作,而在Spring中的Bean的概念则相对比较广泛一些,Spring中的Bean基本上可以包括所有需要使用到的对象,也就是说,基本上在Spring中的对象

  • Spring装配Bean教程之XML安装配置bean详解

    前言 众所周知在Spring刚出现的时候,XML是描述配置的主要方式,在Spring的名义下,我们创建了无数行XML代码.在一定程度上,Spring成为了XML的同义词. 现在随着强大的自动化配置和Java代码的配置出现,XML不再是唯一选择,也不应该是首选,学习XML配置,更多用于维护已有的XML的配置.下面话不多说了,来一起看看详细的介绍吧. 创建XML配置规范 在使用XML配置前,需要创建一个新的配置规范,就像JavaConfig需要我们创建带有 @Configuration注解的类,而在

  • spring在IoC容器中装配Bean详解

    1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean实例放入bean缓存池: 应用程序使用bean. 1.2.基于xml的配置 (1)xml文件概述 xmlns------默认命名空间 xmlns:xsi-------标准命名空间,用于指定自定义命名空间的schema文件 xmlns:xxx="aaaaa"-------自定义命名空间,xx

  • Spring装配Bean之用Java代码安装配置bean详解

    前言 本文主要给大家介绍了关于Spring之利用Java代码安装配置bean的相关内容,尽管通过组件扫描和自动装配实现Spring的自动化配置很方便也推荐,但是有时候自动配置的方式实现不了,就需要明确显示的配置Spring.比如说,想要将第三方库中的组件装配到自己的应用中,这样的情况下,是没办法在它的类上添加 @Compnent和 @Autowired注解的. 在这种情况下,需要使用显示装配的方式,可以分别通过Java和XML实现,推荐使用Java的方式,因为更加强大,类型安全并且重构友好,因为

  • Spring的自动装配Bean的三种方式

    spring的自动装配功能的定义:无须在Spring配置文件中描述javaBean之间的依赖关系(如配置<property>.<constructor-arg>).IOC容器会自动建立javabean之间的关联关系. 如果没有采用自动装配的话,手动装配我们通常在配置文件中进行实现:一下代码就是手动装配: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="ht

  • 详解Spring框架---IOC装配Bean

    IOC装配Bean (1)Spring框架Bean实例化的方式提供了三种方式实例化Bean 构造方法实例化(默认无参数,用的最多) 静态工厂实例化 实例工厂实例化 下面先写这三种方法的applicationContext.xml配置文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"

  • Spring Bean常用的的装配方式详解

    Bean常用的装配方式有3种: 基于xml的装配 基于Annotation(注解)的装配 基于Java配置类的装配 基于xml的装配 在xml文件中配置Bean. 如果依赖很多,xml配置文件会很臃肿,后期维护.升级不方便.自动装配可解决这一问题. 基于xml的自动装配 在<bean>中使用autowired属性完成依赖的自动装配,不再使用<property>手动注入setter方法中的依赖,简化了配置,减少了xml中的代码量. autowire属性的属性值: no 不使用自动装配

  • Spring MVC常用客户端参数接收方式详解

    在MVC结构中,控制器组件主要的功能就是接收请求.处理请求.生成响应,接收客户端传来的请求参数的往往是控制器要做的第一件事. Book实体类Book.java public class Book { private Integer bookId; private String author; //生成Get.Set方法,此处省略 } 一.直接用参数名匹配请求参数 客户端界面(表单): <form action="/queryString" method="post&qu

  • 简单了解Spring Bean常用注解的装配

    这篇文章主要介绍了简单了解Spring Bean常用注解的装配,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 基于注解的装配 在Spring框架中,尽管使用XML配置文件可以很简单地装配Bean,但如果应用中有大量的Bean需要装配,会导致XML配置文件过于庞大,不方便以后的升级与维护,因此更多的时候推荐开发者使用注解(annotation)的方式去装配Bean. 在Spring框架中定义了一系列的注解,下面介绍集中常用的注解. @Compon

  • Spring中Bean的三种实例化方式详解

    目录 一.环境准备 二.构造方法实例化 三.分析Spring的错误信息 四.静态工厂实例化 4.1 工厂方式创建bean 4.2 静态工厂实例化 五.实例工厂与FactoryBean 5.1 环境准备 5.2 实例工厂实例化 5.3 FactoryBean的使用 六.bean实例化小结 一.环境准备 准备开发环境 创建一个Maven项目 pom.xml添加依赖 resources下添加spring的配置文件applicationContext.xml 最终项目的结构如下: 二.构造方法实例化 在

  • Spring Bean注册与注入实现方法详解

    目录 1. 逻辑上的 Bean 注册 2. XML 注册 Bean 到自建的库中 2.1 工厂方法 2.2 使用工厂方法和实例化工厂注册 Bean 3. XML 配合注解进行 Bean 注册 4. 使用注解注册 Bean 4.1 注解方式注册的必要条件 4.2 用到的注解 4.3 @Component注解注入 4.4 使用 @Bean 注解注册 5. 通过注解注入 Bean 6. 注入时的一个坑点 7. 获取 库中的对象 上接[Spring]spring核心思想——IOC和DI 上篇文章结尾简单

  • Spring IOC 常用注解与使用实例详解

    目录 @Component @Autowired @Qualifier @Bean @ImportResource @Profile @PropertySource @Component 注解@component代表spring ioc 会把这个类扫描生成Bean实例 @Component public class Role{ @Value("1") private Long id; @Value("role_name_1") private String role

  • Spring Bean的初始化和销毁实例详解

    本文实例讲述了Spring Bean的初始化和销毁.分享给大家供大家参考,具体如下: 一 点睛 在开发过程中,经常遇到在Bean使用之前或者之后做一些必要的操作,Spring对Bean的生命周期的操作提供了支持. 1 Java配置方式:使用@Bean的initMethod和destroyMethod. 2 注解方式:利用JSR-250的@PostConstruct和@PreDestroy. 二 实战 1 增加JSR250支持 <dependency> <groupId>javax.

  • spring cloud hystrix 超时时间使用方式详解

    我们在使用后台微服务的时候,各个服务之前会有很多请求和交叉业务.这里会引起雪崩.超时等异常处理.SpringCloud Hystrix服务降级.容错机治理使 hystrix 有很好的支持,引入后实现断路器功能. 1:pom 引入jar包 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</a

  • Spring Boot 项目集成Redis的方式详解

    集成方式 使用Jedis Jedis是Redis官方推荐的面向Java的操作Redis的客户端,是对服务端直连后进行操作.如果直接使用Jedis进行连接,多线程环境下是非线程安全的,正式生产环境一般使用连接池进行连接. <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> &

  • Spring 依赖注入的几种方式详解

    IoC 简介 平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过Spring容器帮我们new指定实例并且将实例注入到需要该对象的类中. 依赖注入的另一种说法是"控制反转".通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员. 而控制反转是指new实例工作不由我们程序员来做而是交给Spring容器来做.

随机推荐