场景一:在main函数里得到类的实例
a、通过@Component把类交给Spring管理
b、通过@Configuration实现配置类,并配置Spring@ComponentScan 扫描包下提交的实现类
c、使用场景就是先读区配置类的class,再根据接口的class去匹配实现类
1.1Spring 管理实现类&注入实现类,通过写配置类(注解方式实现配置类,手写接口与实现类的映射)
管理类&注入类,总是需要一个配置文件(来做接口与实现类的映射),上面试通过配置xml文件,这个是通过注解的方式增加一个配置类
HelloService.java
package com.bt.study_spring.demo5;
public interface HelloService {
String hi(String name);
}
HelloServiceImpl.java
package com.bt.study_spring.demo5;
public class HelloServiceImpl implements HelloService {
@Override
public String hi(String name) {
return "hi,"+name;
}
}
HelloConfiguration.java
package com.bt.study_spring.demo5;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 所有的配置
@Configuration
public class HelloConfiguration {
@Bean
public HelloService getHello(){
return new HelloServiceImpl();
}
}
App.java
package com.bt.study_spring.demo5;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(HelloConfiguration.class);
HelloService helloService =context.getBean(HelloService.class);
String str = helloService.hi("帅帅");
System.out.println("str = " + str);
}
}
--------------------
注意:
新增了HelloConfiguration.java 配置类
注入实现类,调用的时候,传的是
ApplicationContext context = new AnnotationConfigApplicationContext(HelloConfiguration.class);
1.2Spring 管理实现类&注入实现类,通过写配置类(注解方式实现配置类,手写接口与实现类的映射)
1、通过注解@Configuration实现一个配置类
2、通过注解@ComponentScan(basePackages = {"com.bt.study_spring.demo6"})
去某个包下扫描哪些实现类交给了Spring管理
2.1 可以不写basePackages = {"com.bt.study_spring.demo6"},默认扫描的位置是
从HelloConfiguration类当前所在的包去扫描哪些实现类交给类Spring管理
2.2 多个扫描包,可以这么写
basePackages = {"com.bt.study_spring.demo6","com.bt.study_spring.demo7"}可以扫描多个包,逗号隔开
3、将接口的实现类通过注解@Component,交给Spring管理
4、使用场景,先读取配置类,再通过配置类与接口类名来匹配对应的实现类。
接口HelloService.java
package com.bt.study_spring.demo6;
public interface HelloService {
String hi(String name);
}
实现类HelloServiceImpl.java
通过@Component交给Spring管理
package com.bt.study_spring.demo6;
import org.springframework.stereotype.Component;
@Component
public class HelloServiceImpl implements HelloService {
@Override
public String hi(String name) {
return "hi,"+name;
}
}
配置类HelloConfiguration.java
注解@Configuration使这个类成为配置类
注解@ComponentScan设置Spring扫描实现类的包
package com.bt.study_spring.demo6;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
// 所有的配置
@Configuration
@ComponentScan(basePackages = {"com.bt.study_spring.demo6"})
// @ComponentScan如果不写basePackages,则默认从HelloConfiguration类当前所在的包去扫描哪些实现类交给类Spring管理
// basePackages = {"com.bt.study_spring.demo6","com.bt.study_spring.demo7"}可以扫描多个包,逗号隔开
public class HelloConfiguration {
}
注入实现类的场景App.java
1、读取实现类
2、通过接口的类名去匹配实现类
package com.bt.study_spring.demo6;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(HelloConfiguration.class);
HelloService helloService =context.getBean(HelloService.class);
String str = helloService.hi("帅帅帅帅");
System.out.println("str = " + str);
}
}
场景二:在类的属性中注入类的实例
管理接口实现类与注入接口的实现类
1、通过注解@Component,把接口实现类交给Spring管理
2、通过注解/配置类/配置文件等方式,去匹配实现类。
2.1使用场景
需要得到接口Hi的实现类的实例,使用@Autowired注入
@Autowired
private Hi hi;
2.2整个过程分两步
1、通过注解@Component把类交给Spring管理
2、通过注解@Autowired注入类的实例
1、通过注解@Component把类交给Spring管理
package com.bt.study_spring.demo8;
import org.springframework.stereotype.Component;
@Component // @Component("hhh") 交给Spring管理,并赋值id=hhh
public class Hi implements HiService{
public void hello(String name){
System.out.println("Hi.hello,"+name);
}
}
a、使用注解@Component把类交给Spring管理
b、这个类的默认id是首写字母小写类的名字,如类HiTom的默认id为hiTom
c、如果想给这个类,添加一个id(方便匹配的时候,根据id去匹配),使用@Component("hhh")
"hhh"为id
2、通过注解@Autowired注入类的实例(最常用)
a、@Autowired 根据接口HiService的类型,去匹配它的实现类
@Autowired // 根据类型匹配
private HiService hiB;
b、实现类有多个时,需要使用@Qualifier("id"),去指定id匹配。指定的内容一定是个bean。如类HiB的默认bean为hi B
根据id匹配,如果想指定id,必须@Autowired 与@Qualifier 一起使用
@Autowired // 根据类型匹配
@Qualifier("hiB") // 根据id匹配,如果想指定id,必须@Autowired 与@Qualifier 一起使用
private HiService hiB;
3、通过注解@Resource注入类的实例
@Resource可是看作是@Autowired与@Qualifier的总和,既可以根据类型匹配,也可以根据id匹配
a、@Resource如果不指定name和type,先根据name找,找不到再根据类型找
@Resource
private HiService hiB;
b、指定id(name)
@Resource(name = "hi")
private HiService hiB;
c、指定类型@Resource(type = )
指定类型@Resource(type = )
private HiService hiB;
2、栗子
接口HelloService
public interface HelloService {
String hi(String name);
}
接口HiService
public interface HiService {
void hello(String name);
}
HelloService实现类HelloServiceImpl
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class HelloServiceImpl implements HelloService {
@Autowired // 根据类型匹配
@Qualifier("hiB") // 根据id匹配,如果想指定id,必须@Autowired 与@Qualifier 一起使用
// @Resource// 指定id:@Resource(name = "hi") 指定类型@Resource(type = )
// @Resource 如果不指定name和type,先根据name找,找不到再根据类型找
private HiService hiB;
@Override
public String hi(String name) {
hiB.hello(name);
return "hi,"+name;
}
}
HiA
import org.springframework.stereotype.Component;
@Component // @Component("hhh") 交给Spring管理,并赋值id=hhh
public class HiA implements HiService{
public void hello(String name){
System.out.println("Hi.hello,"+name);
}
}
HiB
import org.springframework.stereotype.Component;
@Component
public class HiB implements HiService{
@Override
public void hello(String name) {
System.out.println("你好,"+name);
}
}
Demo8Configuration
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class Demo8Configuration {
}
App
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo8Configuration.class);
HelloService helloService = applicationContext.getBean(HelloService.class);
String str = helloService.hi("yy");
System.out.println("str = " + str);
}
}
1、类/实现类交给Spring管理@Compont,可以不写id,默认id为类首字母小写。如果加id格式为@Compont("idname")
2、注入类的实例,@Autowired与@Qualifier。
@Autowired只根据类型匹配。拿到接口,然后去匹配这个接口下的实现类
@Qualifier去匹配实现类的id
3、一个接口下的多个实现类,
4、@Resource(最常用的是@Autowired)
场景三:多实例情况
如场景二,现有实现类 HiA和HiB,但是在HelloServiceImpl注入类型的时候没有标记@QualiFier
接口HiService,并且在实现类 HiA和HiB中没有加@Primary注解
public interface HiService {
void hello(String name);
}
HiA
import org.springframework.stereotype.Component;
@Component // @Component("hhh") 交给Spring管理,并赋值id=hhh
public class HiA implements HiService{
public void hello(String name){
System.out.println("Hi.hello,"+name);
}
}
HiB
import org.springframework.stereotype.Component;
@Component
public class HiB implements HiService{
@Override
public void hello(String name) {
System.out.println("你好,"+name);
}
}
接口HelloService
public interface HelloService {
String hi(String name);
}
HelloService实现类HelloServiceImpl
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class HelloServiceImpl implements HelloService {
@Autowired // 根据类型匹配
// 与场景二比较未加Qualifire
private HiService hiService;
@Override
public String hi(String name) {
hiService.hello(name);
return "hi,"+name;
}
}
那么程序启动的时候会报
***************************
APPLICATION FAILED TO START
***************************
Description:
Field hiService in cn.com.test.controller.HelloServiceImpl required a single bean, but 2 were found:
- hiA : defined in file [D:\classes\cn\com\test\service\impl\HiA.class]
- hiB : defined in file [D:\classes\cn\com\test\service\impl\HiB.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Process finished with exit code 1
报错原因是:hiService 的实现类只能有一个bean,但是找到了两个
解决办法是:考虑将其中一个bean标记为@Primary,更新使用者以接受多个bean,或者使用@Qualifier来标识应该被使用的bean