Spring注解之自动装配

  • 自动装配就是Spring利用依赖注入(DI)完成对IOC容器中各个组件的依赖关系赋值,也就是根据指定的装配规则(可以是属性名,也可以是属性类型),Spring会自动将匹配的属性值在IOC容器中进行注入。

1. xml方式

1.1. xml下的自动装配过程

  • 通过在配置文件中使用bean标签在对bean注入时,使用标签中的autowire属性,可用来完成自动装配,这样就可以完成基于xml方式的自动装配。
 *             autowire属性值:
 *                    byName:根据属性名称注入,但注入值bean的id需要和类属性名一致
 *                    byType:根据属性类型注入,但不能声明多个同类型注入值bean

1.1.1. 代码测试

  • 比如之前讲过的依赖注入中提到,可以使用引用型注入方法,在我们的配置文件中使用property标签的ref属性进行bean引用,或者在property标签中进行bean注入,而自动装配则使用的是bean标签中的autowired属性,如下举例
public class Dept {

    private String deptName;

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getDeptName() {
        return deptName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptName='" + deptName + '\'' +
                '}';
    }
}
             ##########################################
public class Emp {
    private Dept dept;

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Dept getDept() {
        return dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept +
                '}';
    }
    public void test(){
        System.out.println(dept);
    }
}
                      ##################################3333
                                 Spring配置文件
   <bean id="emp" class="com.spring5.autowire.Emp" autowire="byName"></bean>
    <bean id="dept" class="com.spring5.autowire.Dept">
        <property name="deptName" value="实验部"/>
    </bean>
                      ##################################3333
                                 测试代码
    @Test
    public void testAutoWire(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean8.xml");
        com.spring5.autowire.Emp emp = context.getBean("emp", com.spring5.autowire.Emp.class);
        System.out.println(emp);

    }

运行结果:

2. 注解方式

  • 使用注解方式进行自动装配主要应用与我们的日常开发学习中,比如在service层调用dao层;controller层调用service层,需要在一个组件中去调用另一个组件。

2.1. @Autowired自动注入

@Autowired 可以标注在方法和构造器,参数,属性位置,但都是从IOC容器中获取参数组件的值:

 * 方法上:
          Spring 容器创建当前对象时,就会调用被标注的方法完成赋值
          方法所需的参数若是自定义类型,则从IOC容器中获取
          使用@Bean+方法参数,参数从容器中获取,默认不写@Autowired
 * 构造器:
          默认加在IOC容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
          构造器要用的组件,也都是从容器中获取,(当前类(组件)若只有一个有参构造器,@Autowired可省略)
 * 参数:
          同从容器中获取

2.1.1. 代码测试

                                   相关代码
//@Component
public class Car {
    public Car() {
        System.out.println("Car constructor");
    }
}
                           #########################
@Component
public class Boss {

    private Car car;

    public Boss(Car car) {
        System.out.println("Boss args contrastor");
        this.car = car;
    }

    public Car getCar() {
        return car;
    }
   
   
    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "Boss{" +
                "car=" + car +
                '}';
    }
}          
2.1.1. 标注在方法上测试
    @Autowired
    public void setCar(Car car) {
        this.car = car;
    }
  • 当我们不在IOC容器中注册Car组件时获取Boss组件,发生报错
    在这里插入图片描述
  • 在IOC容器中注册Car组件后获取Boss组件
    在这里插入图片描述
2.1.1. 标注在构造器上测试
 @Autowired
 public Boss(Car car) {
        System.out.println("Boss args contrastor");
        this.car = car;
    }

    public Boss(String name, Car car) {
        this.name = name;
        this.car = car;
    }
  • 当存在两个有参构造器时,必须选择一个构造器标识@Autowired注解,否则会报错
    在这里插入图片描述

测试结果:
在这里插入图片描述

2.1.1. 标注在参数上测试
 public void setCar(@Autowired Car car) {
        this.car = car;
    }

测试结果:
在这里插入图片描述

2.2. 如何使用@Autowired注解

1。一个组件需要调用另外一个组件,只需要在被调用的组件上标注@Autowired即可;
默认优先按照类型去容器中找对应的组件,找到就赋值;

2。如果找到多个相同类型的组件,再将属性名作为组件id去容器中查找,也就是在容器中找到了多个类型相同的组件,但组件id肯定不会相同,这个时候就看添加@Autowired注解的属性名是什么 ,优先选择组件ID和属性名一致的组件进行注入(也可以通过修改属性名来选择组件)

3。@Qualifier :指定需要装配的组件的id,而不是使用属性名;就是容器中有多个同类型组件,但是会默认优先选择组件ID同属性名的组件,而此时我们又只想要另一个与属性名不同名的组件,此时,就可以使用@Qualifier注解进行组件指定

4。自动装配默认一定要先对属性进行赋值,可在容器中找到该组件,否则会报错 ,也就是说我们在进行自动装配时,一定要先将组件注入到IOC容器中,使用@Autowired就相当于对属性赋值,而这个赋值就是是在容器中找到对应的组件,将该组件与属性进行绑定,完成属性赋值操作;如果说我们没有在IOC容器中进行组件注册,就需要使用@Autowired(required = false)进行设置,required默认true,就是必须要在容器中注册之后才能进行赋值操作,设置为false之后就是能在容器中找到就进行装配,找不到就不管了,组件赋值为null

5。@Primary:让Spring在进行自动装配时,默认首选注册的bean,也就是容器中有多个同类型组件时,默认优先选择标识@Primary注解的组件,所以该注解与@Qualifier相矛盾,前者是默认优先选择,后者是明确指定,如果同时添加@Qualifier注解,则就继续装配指定的组件了
(当我们按类型在容器中获取某单个bean实例时,如果出现多个同类型bean时会报错,但如果某个组件使用@Primary注解时就会选择@primary注解的bean,如果需要其他组件,此时就需要按照组件名字去容器中获取)

2.2.1. 代码测试

2.2.1.1 一个组件需要调用另外一个组件
                            controller调用service,service调用dao
@Controller
public class BookController {
    @Autowired
    private BookService bookService;

    public BookService getBookService() {
        return bookService;
    }
}

                   #####################################
                             测试代码
    @Test
    public void test3() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyconfigOfAutoWired.class);
        BookController bean = context.getBean(BookController.class);
        System.out.println(bean.getBookService());
    }                             

运行结果:
在这里插入图片描述

2.2.1.2 如果找到多个相同类型的组件,再将属性名作为组件id去容器中查找

在这里插入图片描述

                  ###################################
                        两个dao组件
@Repository 
public class BookDao {
    private String label = "1";  // 识别组件标签
}   

@Bean("bookDao2")
public BookDao bookDao(){
        BookDao bookDao = new BookDao();
        bookDao.setLabel("2");
        return bookDao;
 }          
                   ###################################
                           service            
@Service
public class BookService {

    @Autowired
    private BookDao bookDao;
    
    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}
                   #####################################
                               测试代码
    @Test
    public void test4() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyconfigOfAutoWired.class);
        BookService bean = context.getBean(BookService.class);
        System.out.println(bean);
    }
                               

运行结果:
在这里插入图片描述

2.2.1.3. 指定需要装配的组件的id
@Service
public class BookService {

    @Autowired
    @Qualifier("bookDao2")
    private BookDao bookDao;

}
                    其余代码同上2.1.1.2 ,只需添加 @Qualifier("bookDao2")

运行结果:
在这里插入图片描述

2.2.1.4 required=false
  • 目前我们IOC容器中注册的组件如下
    在这里插入图片描述
  • 当我们去使用@Autowired去为BookService中的bookDao属性来赋值时
@Service
public class BookService {

    @Autowired
    private BookDao bookDao;

    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

,就会报错如下
在这里插入图片描述

  • 代码测试required=false
@Service
public class BookService {

    @Autowired(required = false)
    private BookDao bookDao;

    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

在这里插入图片描述

2.2.1.5. @Primary
    @Bean("bookDao2")
    @Primary
    public BookDao bookDao(){
        BookDao bookDao = new BookDao();
        bookDao.setLabel("2");
        return bookDao;
    }
                     ********************************************
    @Service
    public class BookService {

   	 	@Autowired
   	 	// @Qualifier("bookDao")
    	private BookDao bookDao;

    	@Override
    	public String toString() {
        	return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}
                   ################################################
                                  测试代码
    @Test
    public void test4() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyconfigOfAutoWired.class);
        BookService bean = context.getBean(BookService.class);
        System.out.println(bean);
    }

运行结果:
在这里插入图片描述
去掉@Qualifier(“bookDao”)注释之后运行结果:
在这里插入图片描述

2.3. 了解内容

2.3.1 java规范的JSR250注解

  • Spring支持JSR250的@Resource(jdk11后不支持)和@Inject

@Resource

 可以和@Autowired一样实现自动装配功能,
 默认按照组件名称进行装配,
 但不支持@Primary和@Autowired(required=false) 功能

@Inject

 功能等同@Autowired,
 但无@Autowired(required=false) 功能

2.3.2 自定义组件想要使用Spring容器底层的某些组件,只需要自定义组件实现底层组件的Aware接口,在创建对象的时候,会调用接口规定的方法注入相关组件 (实现Aware接口把Spring底层的一些组件注入到自定义的bean中,比如xxxxAware的功能使用xxxxAwareProcessor)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值