场景一:在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 配置类

spring多个实现类的注入 spring 注入实现类_spring多个实现类的注入

注入实现类,调用的时候,传的是

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