前面我们已经了解到可以有2种方式来加载bean:
XML文件的方式和注解的方式。
http://blog.csdn.net/github_26672553/article/details/78793707
public static void main(String[] args) throws Exception{
// MyConfig类里的代码 好比是我们的xml文件
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
// 从配置文件中设置好了相关验证
UserService userService = (UserService)context.getBean("myUserService"); // 这其实就是通过IoC容器的方式 初始化对象
userService.userLogin("zhangSan","111111111");
}
AnnotationConfigApplicationContext()
其实可以传入多个(打上@Configuration
注解的)类。
实际上项目中有很多个这样的配置类
是很普遍的。
所以,上面我们硬编码的参数就不太合适了。
注解的方式加载Bean:包扫描
<beans>
<context:component-scan base-package="com.acme"/>
</beans>
你也许见过上面这种XML定义的,针对某个package组件扫描。
现在我们并没有采用XML文件定义的方式,如何扫描包(package)?
public static void main(String[] args) throws Exception{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("SpringLean"); // 扫描SpringLean这个包
ctx.refresh();
UserService userService = (UserService)ctx.getBean("myUserService");
userService.userLogin("zhangSan","111111111"); // 打印:用户开始登录...
}
Bean之间相互调用
1、我们创建一个NewsService类
,代码如下:
package SpringLean;
public class NewsService {
// 随便写一个方法吧
public void showTitle(){
System.out.println("这是新闻");
}
}
2、当然为了能够通过注解的方式加载,所以要在MyConfig.java
文件中(这个文件就相当于一个XML配置文件),也可以再创建一个这样的文件:
@Bean
public NewsService myNewsService(){
return new NewsService();
}
我们给myNewsService()
方法打上了@Bean
这个注解。
3、来到入口函数,测试一把
public static void main(String[] args) throws Exception{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("SpringLean"); // 扫描SpringLean这个包
ctx.refresh();
NewsService newsService = ctx.getBean("myNewsService",NewsService.class);
newsService.showTitle(); // 输出:这是新闻
}
4、上面通过注解的方式加载Bean很好理解,但实际开发是复杂的,我们面临很多需求,比如:如果我们要在NewsService类
里怎么调用UserService类
呢?
public class NewsService {
// 随便写一个方法吧
public void showTitle(){
System.out.println("这是新闻");
new UserService(); // 错误
}
}
难道直接在NewsService类
中实例化UserService
?肯定不行。
这样搞,对象之间的关联就不在同一个IoC容器里了。
@Autowired
@Autowired
注解可以实现自动装配,以实现上面的需求。
package SpringLean;
import org.springframework.beans.factory.annotation.Autowired;
public class NewsService {
@Autowired
UserService userService; // 因为在配置类(MyConfig)里有个@bean注解的方法 返回UserService对象,所以这里是可以加载到的
public void showTitle(){
System.out.println("这是新闻");
// 这样就可以在NewsService里 调用到UserService类定义的方法
try {
userService.userLogin("zhangSan","111111111");
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面代码就完成了“在NewsService里调用UserService”。
那么实际有没有作用呢?我们需要测试
public static void main(String[] args) throws Exception{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("SpringLean"); // 扫描SpringLean这个包
ctx.refresh();
NewsService newsService = ctx.getBean("myNewsService",NewsService.class);
newsService.showTitle();
}
我们在入口函数里只调用了NewsService
的showTitle()
方法(这个方法里会调用UserService
的userLogin()
方法),我们看执行后的控制台输出:
这是新闻
用户开始登录...
5、@Autowired
不仅可以作用于属性上,还可以作用于方法上
package SpringLean;
import org.springframework.beans.factory.annotation.Autowired;
public class NewsService {
UserService userService;
@Autowired
public void abc(UserService userService) {
System.out.println("构造函数被自动执行");
this.userService = userService;
}
public void showTitle(){
System.out.println("这是新闻");
// 这样就可以在NewsService里 调用到UserService类定义的方法
try {
userService.userLogin("zhangSan","111111111");
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行输出:
构造函数被自动执行
这是新闻
用户开始登录...
@Qualifier
1、装配冲突
@Bean
public UserService myUserService(){
UserService userService = new UserService();
userService.setUserValidateConfig(this.userValidateConfig1());
return userService;
}
@Bean
public UserService myUS(){
UserService userService = new UserService();
userService.setUserValidateConfig(this.userValidateConfig1());
return userService;
}
如上面代码我们在MyConfig
这个配置类中定义了2个返回UserService对象
的方法,这样就会导致在UserService里使用@Autowired
装配的时候发生“装配冲突”。
因为Autowired默认是以类型进行装配的,定义了2个同类型的,就不知道到底加载哪个了。
2、
@Bean
@Qualifier("us1")
public UserService myUserService(){
UserService userService = new UserService();
userService.setUserValidateConfig(this.userValidateConfig1());
return userService;
}
@Bean
@Qualifier("us2")
public UserService myUS(){
UserService userService = new UserService();
userService.setUserValidateConfig(this.userValidateConfig1());
return userService;
}
我们用不同的Qualifier
来区分。
3、这样加载的时候,只需要
UserService userService;
@Autowired
public void abc(@Qualifier("us1") UserService userService) {
System.out.println("构造函数被自动执行");
this.userService = userService;
}
就不会发生冲突了