概述
之前我们介绍了如何使用注解来自动装配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注解,因为效果都是一样的,都能实现自动装配。
参考
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/99990.html