提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


文章目录

  • Spring中Bean的装配方式
  • Bean的装配方式
  • 1.组件的扫描
  • 2.自动装配-- @Autowired(按类型注入)
  • 3.使用@Bean注解来装配Bean
  • @Component注解和@Bean注解的区别
  • 小结:装配Bean的方式的比较



Spring中Bean的装配方式

Bean的装配方式

1.组件的扫描

(1)@Component注解:定义一个Bean

(2)@ComponentScan注解:对Bean进行扫描
(a)扫描类(默认):@ComponentScan(basePackageClasses = {Person.class}) 被扫描的类必须和当前类在同一个包中

(b)扫描包:@ComponentScan(basePackages = {“com.bean”})
代码部分:

实体类

@Data
@Component(value = "person")
public class Person {
    @Value("李四")
    private String Pname;
    @Value("1003")
    private Integer Pid;
}

对Bean进行扫描

@ComponentScan(basePackages = {"com.bean"})
public class BeanConfig {
}
@Test
    public void t1(){
        //创建一个可以识别注解的Ioc容器,扫描Person类
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
        //获取Person对象
        Person p = (Person) ac.getBean("person");
        System.out.println(p);
    }

结果

Person(Pname=李四, Pid=1003)

2.自动装配-- @Autowired(按类型注入)

(1)@Component注解装配Bean的缺点:只能注入一些简单的值,无法注入对象。

(2)@Autowired注解自动装配Bean优点:

(a)可以减少配置的复杂度

  (b)可以注入对象

(3)原理:Spring容器会根据类型去寻找定义的Bean,找到将其注入

代码部分:

spring怎样指定配置类扫描范围 spring扫描bean_java

实体类

@Data
@Component(value = "person")
public class Person {
    @Value("李四")
    private String Pname;
    @Value("1003")
    private Integer Pid;
}

PersonService接口

public interface PersonService {
    public void printPerson();
}

实体类继承PersonService接口

@Component
public class PersonImpl implements PersonService {
    @Autowired
    private Person person =null;//将类的对象作为成员变量
    @Override
    public void printPerson() {
        System.out.println("姓名:"+person.getPname());
        System.out.println("学号:"+person.getPid());
    }
}

对Bean进行扫描

@ComponentScan(basePackages = {"com.bean","com.impl"})
public class BeanConfig {
}

测试

@Test
    public void t1(){
        //创建一个可以识别注解的Ioc容器,扫描Person类
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
        //获取Person对象
        PersonImpl p =  ac.getBean(PersonImpl.class);
        p.printPerson();
    }
姓名:李四
学号:1003

(4)自动装配的歧义性:Spring建议使用接口编程,每个接口都有一个实现类;但是,在实际开发中一个接口的实现类会有多个,此时自动装配时就有歧义。

(5)消除歧义性的两个注解:

(a)@Primary:代表首要的,作用是告诉IoC容器,请优先使用该类注入

代码部分:

spring怎样指定配置类扫描范围 spring扫描bean_System_02


使用@Primary注解(在有多个实现类的时候优先调用有@Primary注解的实现类)

@Primary
@Component(value = "PersonImpl1")
public class PersonImpl1 implements PersonService {
    @Autowired
    private Person person =null;//将类的对象作为成员变量
    @Override
    public void printPerson() {
        System.out.println("姓名:"+person.getPname());
        System.out.println("学号:"+person.getPid());
    }
}

结果:

姓名:李四
学号:1003

(b)@Qualifier:可以从Ioc容器中通过名称获取对象进行注入(需要给Bean使用@Component注解时要 指定名称)

接口实现类1

@Component(value = "PersonImpl1")
public class PersonImpl1 implements PersonService {
    @Autowired
    private Person person =null;//将类的对象作为成员变量
    @Override
    public void printPerson() {
        System.out.println("姓名:"+person.getPname());
        System.out.println("学号:"+person.getPid());
    }
}

接口实现类2

@Component(value = "PersonImpl2")
public class PersonImpl2 implements PersonService {
    @Autowired
    private Person person = null;
    @Override
    public void printPerson() {
        System.out.println("-----姓名:"+person.getPname());
        System.out.println("-----学号:"+person.getPid());
    }
}

创建一个类调用接口实现类的方法
@Qualifier(value = “PersonImpl2”)注解 实现了接口实现类PersonImpl2的方法

@Component
public class PersonController {
    //白动装配:按类型装配,在给定的包中进行扫描,找到PersonService类型的Bean后就生成实例进行注入
    @Autowired
    @Qualifier(value = "PersonImpl2")
    private PersonService service=null;
    public void getPerson(){
        service.printPerson();
    }
}

打印结果

-----姓名:李四
-----学号:1003

3.使用@Bean注解来装配Bean

1.被 @Bean 注解标注的方法会创建一个 bean 的实例,放在 spring IoC 容器中。等需要使用这个 bean 的时候,在类里用 @Autowired 注入这个对象就行了。

@Component注解和@Bean注解的区别

1.@Component注解只能注解在类上,不能注解在方法上。缺点:在java开发中需要使用第三方的包(jar)时,无法给这些包中的类使用@Component注解,若必须要用只能是新建一个类继承第三方包中的类然后在自己新建的类上使用@Component注解,这就显的不伦不类。

2.@Bean注解:可以用在方法上,方法返回的对象作为Spring的Bean。不能使用在类上
@Bean(name = “roleServiceImpl1”)
‘name’:是一个字符串的数组,运行配置多个BeanName
‘autowire’:标志是一个引用的Bean对象,默认为Autowire.NO
‘initMethod’:自定义初始化方法
‘destroyMethod’:自定义销毁方法

代码部分:
使用@Bean注解后就可以在继承接口的两个实体类中注释掉@Component因为@Bean本身就会创建一个对象存放在Ioc容器中。

@Component
public class PersonController {
    @Autowired
    @Qualifier(value = "PersonImpl1")(实现的是PersonImpl1的方法)
    private PersonService service=null;//白动装配:按类型装配,在给定的包中进行扫描,找到PersonService类型的Bean后就生成实例进行注入
    public void getPerson(){
        service.printPerson();
    }
    @Bean(name = "PersonImpl1")
    public PersonService getPersonImpl1(){
        return new PersonImpl1();
    }
    @Bean(name = "PersonImpl2")
    public PersonService getPersonImpl2(){
        return new PersonImpl2();
    }
}

结果:

姓名:李四
学号:1003

小结:装配Bean的方式的比较

1、装配方式:

(1)在XML文件中显式配置
          (2)在java的接口和类中实现配置
          (3)隐式Bean的发现机制和自动装配(使用注解)

2、装配方式的选择:

(1)基于约定优于配置的原则,优先考虑隐式Bean的发现机制和自动装配原则。优点是减少开发者的决定权,简单又灵活。
	      (2)在没有办法使用自动装配时,优先考虑java接口和类中实现配置
	      (3)若前面两种方法都无法实现时,使用xml方式进行配置