使用@Autowired进行自动注入
Spring通过@Autowired注解实现Bean的依赖注入。
@Autowired默认按照类型(byType)匹配的方式在容器中查找匹配的Bean,当且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class Pilot { @Autowired private Plane plane; public void drivePlane() { plane.fly(); } }
实例
POJO类
package com.xgj.ioc.configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class Pilot { @Autowired private Plane plane; public void drivePlane() { plane.fly(); } }
@Component注解将Pilot标注为一个Bean,Spring会扫描加载并实例化该Bean。
通过@Autowired注入plan的Bean。
POJO类
package com.xgj.ioc.configuration; import org.springframework.stereotype.Component; @Component public class Plane { private String brand; private String color; private int speed; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public void introduce() { System.out.println("Plane information【 brand:" + brand + ",color:" + color + ",speed:" + speed); } public void fly() { System.out.println("Plane begins to fly"); } }
配置文件
<?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.xsd"> <!-- (1)声明Context命名空间以及Schema文件 (2)扫描类包以及应用注解定义的bean --> <context:component-scan base-package="com.xgj.ioc.configuration"/> </beans>
测试类
package com.xgj.ioc.configuration; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ConfigBeanTest { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath:com/xgj/ioc/configuration/beans.xml"); Pilot pilot = ctx.getBean("pilot", Pilot.class); pilot.drivePlane(); Plane plane = ctx.getBean("plane", Plane.class); plane.setBrand("A380"); plane.setColor("White"); plane.setSpeed(800); plane.introduce(); } }
运行结果:
使用@Auotwired的required属性
如果容器中没有一个和标注变量类型匹配的Bean,那么Spring启动的时候会报NoSuchBeanDefinitionException异常。 如果希望Spring及时找不到匹配的Bean完成注入也不要抛出异常,那么就可以使用@Autowired(required=false)进行标注。
实例
还是以上面的例子为基础改造下,我们知道上面的扫描包配置的为
<context:component-scan base-package="com.xgj.ioc.configuration"/>
假设在com.xgj.ioc.configuration之外的包目录下 有个Tank类(com.xgj.ioc.inject.construct.type.Tank)
改造下Pilot类,引入Tank,设置自动注入
package com.xgj.ioc.configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.xgj.ioc.inject.construct.type.Tank; @Component public class Pilot { @Autowired private Plane plane; @Autowired private Tank tank; public void drivePlane() { plane.fly(); } }
@Autowired 默认 required =true
运行测试类:
No qualifying bean of type 'com.xgj.ioc.inject.construct.type.Tank' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
我们改造下@Autowired(required = false)
@Autowired(required = false) private Tank tank;
再此运行: OK
使用@Qualifier指定注入Bean的名称
如果容器中有一个以上匹配的Bean时,则可以通过@Qualifier注解限定Bean的名称。
假设容器中有两个类型为Plane的Bean,一个名为plane,一个名为otherPlane. 因为@Autowired默认是按照类型匹配的方式在容器中查找,plane和otherPlane的类型都是Plane,怎么知道注入哪一个呢?
实例
我们在扫描的基类包下增加个子包 other,包下新增同名Plane类,通过@Component(“otherPlane”)指定Bean的名称。
com.xgj.ioc.configuration.other.Plane代码如下:
package com.xgj.ioc.configuration.other; import org.springframework.stereotype.Component; @Component("otherPlane") public class Plane { private String brand; private String color; private int speed; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public void introduce() { System.out.println("OtherPlane information【 brand:" + brand + ",color:" + color + ",speed:" + speed); } public void fly() { System.out.println("OtherPlane begins to fly"); } }
如果我们希望注入otherPlane呢?
我们来改造Pilot类
package com.xgj.ioc.configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; // 1. 引入其他子包下的Plane import com.xgj.ioc.configuration.other.Plane; import com.xgj.ioc.inject.construct.type.Tank; @Component public class Pilot { @Autowired // 2 通过@Qualifier限定Bean的名称 @Qualifier("otherPlane") private Plane plane; @Autowired(required = false) private Tank tank; public void drivePlane() { plane.fly(); } }
测试类中改动的地方
记得引入 other子包下的Plane
import com.xgj.ioc.configuration.other.Plane; ..... Plane plane = ctx.getBean("otherPlane", Plane.class);
然后运行测试类:
对类方法进行标注
@Autowired可以对类成员变量以及方法的入参进行标注。
下面在类的方法上使用@Autowired注解。
实例
package com.xgj.ioc.configuration.method; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class Pilot { private Plane plane; // 自动将Plane类型传给方法入参 @Autowired public void setPlane(Plane plane) { this.plane = plane; } public void drivePlane() { plane.fly(); } }
如果是下面这种写法
// 自动将名为plane的Bean传给方法入参 @Autowired @Qualifier("plane") public void setPlane(Plane plane) { this.plane = plane点内容**
如果一个方法拥有多个入参,在默认情况下,Spring将自动选择匹配入参类型的Bean进行注入。 Spring允许对方法入参标注@Qualifier以指定注入Bean的名称。
比如
@Autowired public void setPlane(Plane plane, @Qualifier("tank") Tank tank) { this.plane = plane; }
在这种情况下,Plane的入参注入为Plane类型的Bean,而Tank的入参注入的则为名称为tank的Bean.
实例代码如下:
Pilot POJO类
package com.xgj.ioc.configuration.method; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class Pilot { private Plane plane; // 自动将Plane类型传给方法入参 @Autowired public void setPlane(Plane plane) { this.plane = plane; } public void drivePlane() { plane.fly(); } }
Plane POJO类
package com.xgj.ioc.configuration.method; import org.springframework.stereotype.Component; @Component // 通过注解标注为一个Bean,以便Spring扫描并实例化 public class Plane { public void fly() { System.out.println("Plane begins to fly"); } }
配置文件
<?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.xsd"> <!-- (1)声明Context命名空间以及Schema文件 (2)扫描类包以及应用注解定义的bean --> <context:component-scan base-package="com.xgj.ioc.configuration.method"/> </beans>
测试类
package com.xgj.ioc.configuration.method; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ConfigMethodTest { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath:com/xgj/ioc/configuration/method/beans.xml"); Pilot pilot = ctx.getBean("pilot", Pilot.class); pilot.drivePlane(); } }
运行结果