Spring注解驱动开发——自动装配(2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rubulai/article/details/80532245

@Autowired不止可以标注在属性上,也可以标注在构造器、方法、参数上

标注在方法上:

@Component
public class Student {

	private Bike bike;

	public Bike getBike() {
		return bike;
	}

	@Autowired
	public void setBike(Bike bike) {
		this.bike = bike;
	}
	
}

一般标注在Setter方法上,其实可以标注在任何方法上,但是方法一定要有入参。此时,Spring容器在初始化Student对象后就会调用其标注@Autowired的方法,将属性注入进去,注入的方式依然是先根据类型查找,查到多个时再根据参数名匹配。那么问题来了,标注有@Autowired注解的方法是何时调用的呢?如果在被注入的对象创建之前调用肯定是不行的,在从容器中获取Student的实例时该实例就已经有了bike属性值,说明该属性的注入并非在第一次使用时,而是在容器创建bean之后通过后置处理的方式注入的该属性,难道是在容器中所有的Bean都创建完之后才会调用这些@Autowired注解的方法吗?是的,其实是AutowiredAnnotationBeanPostProcessor后置处理器的功劳,在创建完Bean之后会后置处理这些标注有@Autowired注解的方法、属性、入参等那么还有一个问题假如容器中的bean没有无参构造器,但有一个标注了@Autowired注解的有参构造器(在只有一个有参构造器时该构造器上的@Autowired可以省略,就是说隐藏带有@Autowired),此时在创建bean的时候就需要注入属性,那就不是AutowiredAnnotationBeanPostProcessor能解决的了,这时会怎么样呢?这时Spring会将这个Bean的创建时机置后,待其他的Bean都创建完之后再创建该Bean,如果两个类中都有@Autowired注解的构造器,且彼此的构造器中的入参相互引用的话则会报错,因为这两个对象都无法创建,报UnsatisfiedDependencyException异常,此时采用@Autowired(required=false)也不可以,原因也很简单,因为在创建对象时都需要检查彼此有没有创建好,而返回的都是false,所以不可以

标注在构造器上:注意必须是有参构造器

@Component
public class Student {

	private Bike bike;

	@Autowired
	public Student(Bike bike) {
		this.bike = bike;
	}

	public Bike getBike() {
		return bike;
	}

	public void setBike(Bike bike) {
		this.bike = bike;
	}

}

默认情况下,Spring在实例化bean时会调用类的无参构造器,但是在类提供了有参构造器时,如果有参构造器上有@Autowired注解,Spring则会调用该有参构造器创建实例,如果没有,则还是调无参构造器(无参构造器存在)。那么问题来了,如果类中既有无参构造,又有@Autowired注解的有参构造,或者有多个@Autowired注解的有参构造时Spring会怎么创建实例呢?在有多个@Autowired标注的构造器时会报错,在仅有一个@Autowired标注的构造器时,会调用@Autowired标注的构造器,如果只有一个有参构造器时,@Autowired可以省略。

标注在参数上:作用和标注在方法上是一样的,只不过标注在参数上可以更精确的指明哪些参数需要由Spring注入,哪些不必由Spring注入

@Component
public class Student {

	private Bike bike;

	private Car car;

	public Student(@Autowired Bike bike, Car car) {
		this.bike = bike;
		this.car = car;
		System.out.println("两个参数...");
	}

	public Bike getBike() {
		return bike;
	}

	public void setBike(Bike bike) {
		this.bike = bike;
	}

	public Car getCar() {
		return car;
	}

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

}

容器类中@Bean注解的方法的入参的实例也是从容器中获取的:相当于入参的位置加了@Autowired,此时入参位置的bean必须能在容器中找到,否则会报错,如果不想使其报错,可以使用required=false指明其并非必须的

@Configuration
@ComponentScan("com.bdm.modle")
public class AutowiredConfig {

	@Bean
	public Student student(Car car, @Autowired(required = false) Bike bike) {
		Student student = new Student();
		student.setBike(bike);
		student.setCar(car);
		return student;
	}
}

在IOC容器中的bean的方法的入参中如果有Spring的底层类型,则会自动注入进去

@Component
public class Car {
	public Car(ApplicationContext applicationContext) {
		String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
		for (String string : beanDefinitionNames) {
			System.out.println(string);
		}
	}
}

此处构造器中的ApplicationContext会由容器注入进去

猜你喜欢

转载自blog.csdn.net/rubulai/article/details/80532245