Spring注入的方式

365 阅读4分钟

日积月累,水滴石穿 😄

方式几种

整体可以分为:xml 方式、注解方式

  • xml
    • 手动: 构造方法(constructor-arg)、set方法(property)
    • 自动:byName、byType、constructor

xml方式

手动

我们先来看下每种方式是怎么使用的!

构造方法

提供两个类,一个是 OrderService,另外一个是 UserServiceUserService 中包含OrderService 属性,一个test方法,一个有参构造方法和一个无参构造方法

public class OrderService {
}

public class UserService {

	OrderService orderService;

	public UserService(){
		System.out.println("xml 无参构造注入" + orderService);
	}
	public UserService(OrderService orderService1){
		System.out.println("xml 有参构造注入" + orderService1);
		orderService = orderService1;
	}
	
	public void test(){
		System.out.println(orderService);
	}
}

我们可以看一下 xml 中的配置方式, constructor-arg 标签

<bean class="com.gongj.populateBean.OrderService" id="orderService"></bean>

<bean class="com.gongj.populateBean.UserService" id="userService">
   <constructor-arg index="0" ref="orderService"></constructor-arg>
</bean>
验证
public static void main(String[] args) {
		ClassPathXmlApplicationContext context =
				new ClassPathXmlApplicationContext("spring-config2.xml");
		UserService bean = context.getBean(UserService.class);
		bean.test();
}
结果:
xml 有参构造注入com.gongj.populateBean.OrderService@14514713
com.gongj.populateBean.OrderService@14514713

set方式

新增一个setOrder方法。这个setOrder方法用来注入 OrderService 的。


	public void setOrder(OrderService order){
		System.out.println("xml property方法注入" + order);
		orderService = order;
	}

修改 xml 中的配置方式,注意看 UserService的配置,将 constructor-arg 标签修改为了 property 标签,name 配置的值是 UserService 类中 setOrder的名称(省略set并首字母小写) ,ref 配置的值是上方OrderServiceid属性值,也就是 beanName

	<bean class="com.gongj.populateBean.OrderService" id="orderService">
	</bean>

	<bean class="com.gongj.populateBean.UserService" id="userService">
		<property name="order" ref="orderService"></property>
	</bean>
set方式验证
xml 无参构造注入null
xml property方法注入com.gongj.populateBean.OrderService@255316f2
com.gongj.populateBean.OrderService@255316f2

没有指定构造方法,默认走无参构造。

自动

先提一下 bean 标签里有个属性 autowire,这个属性的值有五种情况:nobyNamebyTypeconstructorautodetect

  • no:默认值,也就是不使用自动注入,也就是上面那种两种手动方式,在 xml 中配置 property标签或者 constructor-arg标签

  • byName:根据实体类中的set方法名称进行自动注入,不需要再配置 property标签

  • byType:根据实体类中的set方法的参数类型进行自动注入。

  • constructor:根据构造函数进行匹配,不需要再配置 constructor-arg标签。

  • autodetect:如果有默认的构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配,Spring3.0被弃用。

byName

  • 反例:
public void setOrder(OrderService order){
		orderService = order;
}

就根据 order 这个名称(省略set并首字母小写)作为 beanName 去寻找Bean。如果找到了对应的Bean,才会将 Bean 赋值给方法的参数,并执行set方法。否则不会发生任何改变。(PS:当然在本例中,根据 order 这个名称是找不到 bean的,因为在xml配置的 beanName 叫 orderService,所以需要增加 set 方法并方法名称为 setOrderService

  • 正例
public void setOrderService(OrderService order){
		System.out.println("byName 方法注入" + order);
		orderService = order;
}
结果:
xml 无参构造注入null
byName 方法注入com.gongj.populateBean.OrderService@255316f2
com.gongj.populateBean.OrderService@25531

byType

根据 OrderService这个类型去寻找。如果找到多个相同类型则抛出异常。只需将byName修改为byType就会出现下面这种情况:

结果:
xml 无参构造注入null
xml property方法注入com.gongj.populateBean.OrderService@6e5e91e4
byName 方法注入com.gongj.populateBean.OrderService@6e5e91e4
com.gongj.populateBean.OrderService@6e5e91e4

这是由于 setOrder方法与setOrderService方法的参数类型都是 OrderService

constructor

在之前 UserService的基础上再增加一个有参构造方法。将byType修改为constructor

  • 示例
public UserService(OrderService orderService1,OrderService orderService2){
		System.out.println("两个参数有参构造注入" + orderService1 +"==="+ orderService2);
		orderService = orderService1;
}
结果:
两个参数有参构造注入com.gongj.populateBean.OrderService@46fbb2c1===com.gongj.populateBean.OrderService@46fbb2c1
com.gongj.populateBean.OrderService@46fbb2c1

如果有多个构造方法,会调用参数多的那个构造方法。

注解方式

随着 Spring 的发展,许许多多的注解可以替换xml的配置了,比如 @Bean替换了<bean>@Scope替换了 scope@Autowired 替换了 autowire 等等。我们这篇就使用一下 @Autowired的注入方式。

使用 @Autowired 注解了呢,就可以省略上面所写的 set 方法了。

public class UserService {
	@Autowired
	OrderService orderService;

	public void test(){
		System.out.println(orderService);
	}
}

可以看到UserService类里面就变得很简洁了。由于这里使用的是 ClassPathXmlApplicationContext这个容器,所以需要在 xml 中增加配置,如下:

<context:annotation-config/>

这个配置的作用是:激活已经在Spring容器里注册过的bean,我们已经通过 xml 的方式向 Spring 注册 Bean了。

当然你可能会觉得既然我都使用注解了,为什么还要在 xml 中注册 bean 呢?如果你有这种想法,你可以使用下面一种方式,在 xml 中增加配置,指定扫描包路径,如下:

<context:component-scan base-package="com.gongj.populateBean"/>

作用:具备 <context:annotation-config> 的所有功能,还可以扫描指定的 package 下面的类并注册为bean。

在类上加上注解Component,将该类注册到 Spring 容器中

@Component
public class UserService {}

如果你完全都不想有 xml 文件,那你可以使用如下方式:

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppApplication.class);

切换容器,使用AnnotationConfigApplicationContext

新增 AppApplication类,类的内容如下:

@ComponentScan(basePackages = {"com.gongj.populateBean"})
public class AppApplication {
}

使用 ComponentScan注解指定扫描包路径。上述代码不再概述。

OK!我们回到正题 @Autowired 注解。使用了Autowired 注解之后,我们可以省略掉 set 方法,增加了我们的摸鱼时间 (* ̄︶ ̄)!

  • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。