第二章IOC控制反转,DI注入分类(基于注解的 DI)

       对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 bean 实例。 Spring 中使用注解, 需要在原有 Spring 运行环境基础上再做一些改变。
项目结构
 需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解。
指定多个包的方式三种方式,
(1)使用多个context:component-scan指定不同的包的路径
(2)使用base-package的值,使用分隔符
分隔符可以是 逗号(,)分号(;)还可以使用空格,不建议使用空格。
逗号分隔:
分号分隔
(3)base-package是指定到父包名
base- package的值表是基本包,容器启动会自动扫描包,及其子包中的注解,当然也会扫描到子包下级的子包。所以base-package可以指定一个父包就可以。

 整个applicationContext.xml文件的内容

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
<!--声明组件扫描器,指定注解所在的包名-->
<!--    <context:component-scan base-package="com.it.bao1"/>-->
<!--    <context:component-scan base-package="com.it.bao3"/>-->
<!--    <context:component-scan base-package="com.it.bao5"/>-->
<!--    <context:component-scan base-package="com.it.bao6"/>-->


<!--    指定多个包的三种方式-->
<!--    第一种-->
<!--    <context:component-scan base-package="com.it.bao1"/>-->
<!--    <context:component-scan base-package="com.it.bao2"/>-->
<!--第二种-->
<!--    <context:component-scan base-package="com.it.bao1,com.it.bao3"/>-->
<!--    <context:component-scan base-package="com.it.bao1;com.it.bao2"/>-->
<!--    第三种-->
<!--    <context:component-scan base-package="com.it"/>-->
</beans>

         applicationContext.xml文件有了组件扫描器,就可以对该组件扫描器所指定包下的类文件进行注解配置。

2.4.1 定义 Bean 的注解 @Component
需要在类上使用注解 @Component ,该注解的 value 属性用于指定该 bean id 值。@Component 不指定 value 属性, bean id 是类名的首字母小写。
另外, Spring 还提供了 3 个创建对象的注解:
@Repository 用于对 DAO 实现类进行注解
@Service 用于对 Service 实现类进行注解
@Controller 用于对 Controller 实现类进行注解
        这三个注解与 @Component 都可以创建对象,但这三个注解还有其他的含义, @Service创建业务层对象,业务层对象可以加入事务功能, @Controller 注解创建的对象可以作为处 理器接收用户的请求。
       @Repository @Service @Controller 是对 @Component 注解的细化,标注不同层的对象。即持久层对象,业务层对象,控制层对象。

2.4.2 简单类型属性注入 @Value
       需要在属性上使用注解 @Value ,该注解的 value 属性用于指定要注入的值。
       使用该注解完成属性注入时,类中无需 setter 。当然,若属性有 setter ,则也可将其加到 setter 上。

 结合:组件扫描器定义 Bean 的注解@Component,简单类型属性注入@Value三种方式的第一个练习

1.创建Student

package com.it.bao1;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//该注解是用来创建对象的,等同于<bean>的功能
//value就是对象的名称,等同于<bean>中的id值
//spring容器中的对象遵循单例原则,创建的对象的名字是唯一的。
//component注解写在类的上面

//省略value时
//@Component("myStudent")
//使用value时
@Component(value = "myStudent")
//不指定对象名称,由spring提供默认名称
//@Component
public class Student {

    /**
     * @value简单类型的属性赋值
     *属性:value是String类型的,表示简单类型的属性值
     * 位置:1.在属性定义的上方,无需set方法,推荐使用
     * 2.在set方法的上方,用到了set方法
     */


@Value(value = "小红")
    private String name;
@Value(value = "22")
    private int age;

    public Student() {
        System.out.println("调用student无参数构造方法");
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.创建spring的配置文件applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
<!--声明组件扫描器,指定注解所在的包名-->
    <context:component-scan base-package="com.it.bao1"/>
<!--    <context:component-scan base-package="com.it.bao3"/>-->
<!--    <context:component-scan base-package="com.it.bao5"/>-->
<!--    <context:component-scan base-package="com.it.bao6"/>-->


<!--    指定多个包的三种方式-->
<!--    第一种-->
<!--    <context:component-scan base-package="com.it.bao1"/>-->
<!--    <context:component-scan base-package="com.it.bao2"/>-->
<!--第二种-->
<!--    <context:component-scan base-package="com.it.bao1,com.it.bao3"/>-->
<!--    <context:component-scan base-package="com.it.bao1;com.it.bao2"/>-->
<!--    第三种-->
<!--    <context:component-scan base-package="com.it"/>-->
</beans>

3.创建测试文件

package com.it;

import static org.junit.Assert.assertTrue;

import com.it.bao1.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Unit test for simple App.
 */
public class AppTest 
{

    @Test
    public void test1(){
        String config="applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
}

4.结果展示

 2.4.3 byType 自动注入@Autowired

        需要在引用属性上使用注解 @Autowired ,该注解默认使用 按类型自动装配 Bean 的方式。
        使用该注解完成属性注入时,类中无需 setter 。当然,若属性有 setter ,则也可将其加 setter 上。

测试:

1.创建School类

package com.it.bao3;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "mySchool")
public class School {
    @Value(value = "清华大学")
    private String name;
    @Value(value = "中国北京")
    private String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

2.创建Student类

package com.it.bao3;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//该注解是用来创建对象的,等同于<bean>的功能
//value就是对象的名称,等同于<bean>中的id值
//spring容器中的对象遵循单例原则,创建的对象的名字是唯一的。
//component注解写在类的上面

//省略value时
//@Component("myStudent")
//使用value时
@Component(value = "myStudent")
//不指定对象名称,由spring提供默认名称
//@Component
public class Student {

    /**
     * @value简单类型的属性赋值
     *属性:value是String类型的,表示简单类型的属性值
     * 位置:1.在属性定义的上方,无需set方法,推荐使用
     * 2.在set方法的上方,用到了set方法
     */

@Value(value = "小红")
    private String name;
@Value(value = "22")
    private int age;

    /**
     * 引用类型的赋值
     * @AutoWired:这是spring框架提供的注解,实现引用类型的赋值
     *使用的是自动注入原则,支持byName,byType
     * 默认使用的是byType的自动注入
     * 位置:1.在属性定义的上方,无需set方法,推荐使用
     *       2.在set方法的上方,用到了set方法
     */

    @Autowired

    private School school;

    public Student() {
        System.out.println("调用student无参数构造方法");
    }
    

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

3.创建applicationContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">
<!--声明组件扫描器,指定注解所在的包名-->
<!--    <context:component-scan base-package="com.it.bao1"/>-->
    <context:component-scan base-package="com.it.bao3"/>
<!--    <context:component-scan base-package="com.it.bao5"/>-->
<!--    <context:component-scan base-package="com.it.bao6"/>-->


<!--    指定多个包的三种方式-->
<!--    第一种-->
<!--    <context:component-scan base-package="com.it.bao1"/>-->
<!--    <context:component-scan base-package="com.it.bao2"/>-->
<!--第二种-->
<!--    <context:component-scan base-package="com.it.bao1,com.it.bao3"/>-->
<!--    <context:component-scan base-package="com.it.bao1;com.it.bao2"/>-->
<!--    第三种-->
<!--    <context:component-scan base-package="com.it"/>-->
</beans>

4.创建测试类

package com.it;

import com.it.bao3.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Unit test for simple App.
 */
public class AppTest3
{

    @Test
    public void test1(){
        String config="applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
}

结果

2.4.4 byName 自动注入@Autowired @Qualifier

        需要在引用属性上联合使用注解 @Autowired @Qualifier @Qualifier value 属性用于指定要匹配的 Bean id 值。类中无需 set 方法,也可加到 set 方法上。

测试:

1.创建School类

同上

2.创建Student类

package com.it.bao3;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//该注解是用来创建对象的,等同于<bean>的功能
//value就是对象的名称,等同于<bean>中的id值
//spring容器中的对象遵循单例原则,创建的对象的名字是唯一的。
//component注解写在类的上面

//省略value时
//@Component("myStudent")
//使用value时
@Component(value = "myStudent")
//不指定对象名称,由spring提供默认名称
//@Component
public class Student {

    /**
     * @value简单类型的属性赋值
     *属性:value是String类型的,表示简单类型的属性值
     * 位置:1.在属性定义的上方,无需set方法,推荐使用
     * 2.在set方法的上方,用到了set方法
     */

@Value(value = "小红")
    private String name;
@Value(value = "22")
    private int age;

    /**
     * 引用类型的赋值
     * @AutoWired:这是spring框架提供的注解,实现引用类型的赋值
     *使用的是自动注入原则,支持byName,byType
     * 默认使用的是byType的自动注入
     * 位置:1.在属性定义的上方,无需set方法,推荐使用
     *       2.在set方法的上方,用到了set方法
     */

//    @Autowired
//    通过byName自动注入
    @Autowired
   @Qualifier(value = "mySchool")
    private School school;

    public Student() {
        System.out.println("调用student无参数构造方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

3.创建applicationContext.xml配置文件

同上

4.创建测试类

同上

结果

 同上

           @Autowired 还有一个属性 required ,默认值为 true ,表示当匹配失败后,会终止程序运行。若将其值设置为 false ,则匹配失败,将被忽略,未匹配的属性值为 null

2.4.5 JDK 注解 @Resource 自动注入
       spring提供了对jdk中@resource注解的支持。 @Resource 注解既可以按名称匹配 Bean ,也可以按类型匹配 Bean 默认是按名称注入 。使用该注解,要求 JDK 必须是 6 及以上版本。 @Resource 可在属性上,也可在 set 方法上。

1 byType 注入引用类型属性
       @Resource 注解若不带任何参数,采用 默认按名称 的方式注入,按名称不能注入 bean ,则会按照类型进行 Bean 的匹配注入。

2byName 注入引用类型属性

         @Resource 注解指定其 name 属性,则 name 的值即为按照名称进行匹配的 Bean id 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

做一道光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值