勿将今日事留到明日
方式几种
整体可以分为:xml 方式、注解方式
xml
- 手动: 构造方法(constructor-arg)、set方法(property)
- 自动:byName、byType、constructor
xml方式
手动
我们先来看下每种方式是怎么使用的!
构造方法
提供两个类,一个是 OrderService
,另外一个是 UserService
,UserService
中包含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
配置的值是上方OrderService
的id
属性值,也就是 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
,这个属性的值有五种情况:no
、byName
、byType
、constructor
、autodetect
- 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 方法,增加了我们的摸鱼时间 (* ̄︶ ̄)!
- 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。