Spring注解驱动之方法、构造器上的自动装配

导读:本篇文章讲解 Spring注解驱动之方法、构造器上的自动装配,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

概述

之前我们介绍了如何使用注解来自动装配Spring组件。之前讲的都是在类字段上添加注解,如果在方法、构造器上如何装配呢?下面我们一起来探讨下方法、构造器位置上的自动装配。

@Autowired注解

在这里插入图片描述
我们通过@Autowired注解的源码可以看出,@Autowired注解不仅可以标注在字段上,而且还可以标注在构造方法、实例方法以及参数上。

案例

准备

首先,我们在项目中新建一个Boss类,在Boss类中有一个Car类的引用,并且我们使用@Component注解将Dog类加载到IOC容器中,如下所示。

package com.meimeixia.bean;

import org.springframework.stereotype.Component;

// 默认加在IOC容器中的组件,容器启动会调用无参构造器创建对象,然后再进行初始化、赋值等操作
@Component
public class Boss {
	
	private Car car;

	public Car getCar() {
		return car;
	}

	public void setCar(Car car) {
		this.car = car;
	}

	@Override
	public String toString() {
		return "Boss [car=" + car + "]";
	}	
}

注意,Car类上也要标注@Component注解,即它也要被加载到IOC容器中。
新建好以上Boss类之后,我们还需要在MainConfigOfAutowired配置类的@ComponentScan注解中进行配置,使其能够扫描com.meimeixia.bean包下的类,如下所示。

package com.meimeixia.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.meimeixia.dao.BookDao;

/**
 *
 * @author liayun
 *
 */
@Configuration
@ComponentScan({"com.meimeixia.service", "com.meimeixia.dao", "com.meimeixia.controller", "com.meimeixia.bean"})
public class MainConfigOfAutowired {
	
	@Primary
	@Bean("bookDao2")
	public BookDao bookDao() {
		BookDao bookDao = new BookDao();
		bookDao.setLable("2");
		return bookDao;
	}
}

此时,我们可以直接在Boss类中的car字段上添加@Autowired注解,使其自动装配。
下面我们使用其他的方式来实现car的自动装配。

标注在实例方法上

我们可以将@Autowired注解标注在setter方法上,如下所示。

@Autowired 
public void setCar(Car car) {
    this.car = car;
}

当@Autowired注解标注在方法上时,Spring容器在创建当前对象的时候,就好调用相应的方法为对象赋值。如果标注的方法存在参数时,那么方法使用的参数需要从IOC容器中获取。

然后,我们将IOCTest_Autowired类的test01()方法中有关获取和打印BookService信息的代码注释掉,新增获取和打印Boss信息的代码,如下所示。

package com.meimeixia.test;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.meimeixia.bean.Boss;
import com.meimeixia.config.MainConfigOfAutowired;
import com.meimeixia.service.BookService;

public class IOCTest_Autowired {
	
	@Test
	public void test01() {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
		Boss boss = applicationContext.getBean(Boss.class);
		System.out.println(boss);
		applicationContext.close();
	}
}

运行以上test01()方法进行测试,可以看到,结果信息中输出了如下一行信息。
在这里插入图片描述
说明已经获取到了car的信息,也就是说可以将@Autowired注解标注在方法上。
为了验证最终的输出结果是否是从IOC容器中获取的,我们可以在IOCTest_Autowired类的test01()方法中直接获取Car对象的信息,如下所示。

package com.meimeixia.test;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.meimeixia.bean.Boss;
import com.meimeixia.bean.Car;
import com.meimeixia.config.MainConfigOfAutowired;
import com.meimeixia.service.BookService;

public class IOCTest_Autowired {
	
	@Test
	public void test01() {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowired.class);
		Boss boss = applicationContext.getBean(Boss.class);
		System.out.println(boss);
		Car car = applicationContext.getBean(Car.class);
		System.out.println(car);	
		applicationContext.close();
	}
}

我们再次运行以上test01()方法进行测试,可以在输出的结果信息中看到如下两行内容。
在这里插入图片描述
这已然说明在Boss类中通过@Autowired注解获取到的Car对象和直接从IOC容器中获取到Car对象是同一个对象。

标注在构造方法上

在上面的案例中,我们在Boss类上使用了@Component注解,如下所示。

package com.meimeixia.bean;

import org.springframework.stereotype.Component;

// 默认加在IOC容器中的组件,容器启动会调用无参构造器创建对象,然后再进行初始化、赋值等操作
@Component
public class Boss {
	private Car car;

	public Car getCar() {
		return car;
	}

    @Autowired
	public void setCar(Car car) {
		this.car = car;
	}

	@Override
	public String toString() {
		return "Boss [car=" + car + "]";
	}	
}

此时,Spring会默认将该类加载进IOC容器中,IOC容器启动的时候默认会调用bean的无参构造器创建对象,然后再进行初始化、赋值等操作。
接下来,我们为Boss类添加一个有参构造方法,然后去除setCar()方法上的@Autowired注解,将@Autowired注解标注在有参构造方法上,并在构造方法中打印一条信息,如下所示。

package com.meimeixia.bean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

// 默认加在IOC容器中的组件,容器启动会调用无参构造器创建对象,然后再进行初始化、赋值等操作
@Component
public class Boss {
	private Car car;
	
	@Autowired
	public Boss(Car car) {
		this.car = car;
		System.out.println("Boss...有参构造器");
	}

	public Car getCar() {
		return car;
	}

	public void setCar(Car car) {
		this.car = car;
	}

	@Override
	public String toString() {
		return "Boss [car=" + car + "]";
	}	
}

接着,我们运行IOCTest_Autowired类中的test01()方法进行测试,可以看到输出结果信息中存在如下一行信息。
在这里插入图片描述
说明IOC容器在启动的时候调用了Boss类的有参构造方法。并且还可以从输出的如下两行信息中看出,通过Boss类的toString()方法打印出的Car对象和直接从IOC容器中获取的Car对象是同一个对象。

需要大家注意的是,使用@Autowired注解标注在构造方法上时,构造方法的参数对象也是从IOC容器中获取的。
使用@Autowired注解标注在构造方法上时,如果组件中只有一个有参构造方法,那么这个有参构造方法上的@Autowired注解可以省略,并且参数位置的组件还是可以自动从IOC容器中获取。

标注在参数上

我们也可以将@Autowired注解标注在参数上,例如,在Boss类中我们将构造方法上的@Autowired注解标注在构造方法的参数上,如下所示。

public Boss(@Autowired Car car) {
    this.car = car;
    System.out.println("Boss...有参构造器");
}

当然了,也可以将@Autowired注解标注在setter方法的参数上,如下所示。

public void setCar(@Autowired Car car) {
    this.car = car;
}

最终的效果与标注在字段、实例方法和构造方法上的效果都是一样的。

于是,我们可以得出结论:无论@Autowired注解是标注在字段上、实例方法上、构造方法上还是参数上,参数位置的组件都是从IOC容器中获取。

如果Spring的bean中只有一个有参构造方法,并且这个有参构造方法只有一个参数,这个参数还是IOC容器中的对象,当@Autowired注解标注在这个构造方法的参数上时,那么我们可以将其省略掉,如下所示。

public Boss(/*@Autowired*/ Car car) {
    this.car = car;
    System.out.println("Boss...有参构造器");
}

@Bean注解的方法参数自动装配

我们可以将Car对象作为一个参数传递到MainConfigOfAutowired配置类的color()方法中,并且将该Car对象设置到Color对象中,如下所示。

@Bean
public Color color(Car car) {
    Color color = new Color();
    color.setCar(car);
    return color;
}

当然了,我们也可以使用@Autowired注解来标注color()方法中的car参数,就像下面这样。

@Bean
public Color color(@Autowired Car car) {
    Color color = new Color();
    color.setCar(car);
    return color;
}

总结

  • 如果方法中只有一个IOC容器中的对象作为参数,当@Autowired注解标注在这个方法的参数上时,我们可以将@Autowired注解省略掉。
  • @Bean注解标注的方法在创建对象的时候,方法参数的值是从IOC容器中获取的,此外,标注在这个方法参数上的@Autowired注解可以省略。
  • 使用@Bean注解+方法参数这种形式,此时,该方法参数的值从IOC容器中获取,并且还可以默认不写@Autowired注解,因为效果都是一样的,都能实现自动装配。

参考

Spring注解驱动开发第22讲——如何实现方法、构造器位置的自动装配?我这样回答让面试官很满意!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/99990.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!