# 使用注解前提

如果需要使用注解的方式,那么就必须要用到 spring=aop这个包,否则的话,不能使用注解,但是使用maven,导入spring-context依赖的时候,就会自动导入这个包

# 使用

# 步骤

  • 加入maven依赖,spring-context,在加入这个依赖的时候,会间接的加入spring-aop依赖,这个依赖是注解必须的
  • 在类中使用spring注解,有多个不同功能的注解
  • 在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
  1. 使用注解

    在这个类的上,加上@Component注解

    @Component(value = "zs")
    public class Student {
        private String name;
        private int age;
    
    1
    2
    3
    4

    这个注解的作用,相当于是创建对象的作用,所以上面的注解,就相当于创建了一个zs的对象,这个注解的值,是一个唯一值,这个注解相当于

    <bean id="myStudent" class="com.bjpowernode.ba01.Student" />

  2. 创建组件扫描器

    如果使用了注解之后,一定要使用组件扫描器,需要创建一个配置文件

    <context:component-scan base-package="vin.cco.domain" />

    其中,base-package="vin.cco.domain"这个是一个包名路径,不是类的全限定名称

    其工作原理是,添加了这个标签之后,spring就会自动扫描这个包中,和子包中的所有的类,会在这些类中寻找有这个注解的类,如果有,则会创建对象,或者是给属性赋值

    加入这个组件扫描器之后,配置文件会有什么变化

    1. 会自动的加上一个约束文件(idea会自动加上)
    2. 给约束文件,起一个别名空间

    最初spring配置文件中的代码为

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    </beans>
    
    1
    2
    3
    4
    5
    6

    但是加上这个组件扫描器之后,idea就会自动加上一个约束

    <?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="vin.cco.domain" />
    </beans>
    
    1
    2
    3
    4
    5
    6
    7

# 测试

//这是一个注解,相当于创建一个对象的功能 这个值是唯一的,
@Component(value = "zs")
public class Student {
    private String name;
    private int age;

    public String getName () {
        return name;
    }

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

    public int getAge () {
        return age;
    }

    public void setAge (int age) {
        this.age = age;
    }

    @Override
    public String toString () {
        return "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

测试类

@Test
public void test() throws Exception {
    String path = "anno1.xml";
    ApplicationContext context = new ClassPathXmlApplicationContext(path);

    Student zs = (Student) context.getBean("zs");
    System.out.println(zs);
}
1
2
3
4
5
6
7
8

成功输出,这个的context.getBean("zs");参数的值,就是注解中的那个value值

# 注解区别

除了Component能够创建对象之外,还有几个注解,他们也能创建对象,但是他们之间的功能又存在不同,

  • @Repository(用在持久层类的上面) : 放在dao的实现类上面,必须要放在实现类上面,因为接口是不能够进行创建对象的

    表示创建dao对象,dao对象是能访问数据库的。

  • @Service(用在业务层类的上面):放在service的实现类上面,

    创建service对象,service对象是做业务处理,可以有事务等功能的。

  • @Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,

    控制器对象,能够接受用户提交的参数,显示请求的处理结果。

@Repository,@Service,@Controller是给项目的对象分层的。

他们之间虽然都是用于创建对象,但是他们之间的功能并不是一样的,各有各的功能

那么什么时候使用@Component,先看他有没有mvc三层结构的功能,如果都没有的话,那么我们就使用@component进行对象的创建

# 使用注解的几种方式

因为@component注解中,只有一个value,所以我们可以省略value不写@Component("zs")

也可以直接写@Component(),但是如果是这种的话,那么context.getBean("student")就需要使这个类名的首字母小写

# 扫描多个包的方式

  • 使用多个<context:component-scan base-package="vin.cco.domain" />标签,这个标签可以使用多次

  • 使用分号;或者逗号,进行分割,这种方式,也可以扫描多个包

    <context:component-scan base-package="vin.cco.domain;vin.cco.domain1" />

  • 使用多个包共同的父包

    <context:component-scan base-package="vin" />

    但是这种方式的话,不是很推荐使用,因为可能这个vin包中,含有很多个子包,那么在启动程序的时候,加载资源花费的时间,就会变得非常多

# 对属性的赋值操作

使用注解@Value对属性进行赋值的两种操作

  • 在属性名上使用,这种方式,不需要有set方法,推荐使用

    //@Value("chuchen")
    private String name;
    
    //@Value("20")
    private int age;
    
    1
    2
    3
    4
    5
  • 在set方法上使用,原理是调用set方法进行赋值,所以如果此set方法中,还含有其他的代码块的话,也会执行,不太推荐使用

    @Value("qsyyke")
    public void setName (String name) {
        this.name = name;
    }
    
    @Value("20")
    public void setAge (int age) {
        System.out.println("chuchen blog");
        this.age = age;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 对引用类型进行赋值操作

使用@Autowired()注解对引用类型进行赋值操作,对引用类型进行赋值操作,不能使用@Value注解进行,因为这个注解中,传入的是一个String类型,只能对int,String等赋值,对引用赋值,需要使用@Autowired()

同样也是有两种写法,在属性上面,在set方法上面

但是推荐在属性上面进行赋值操作

@Component("bs")
public class School {
    @Value("保山学院")
    private String name;
    @Value("云南保山")
    private String address;

    @Override
    public String toString () {
        return "School{" + "name='" + name + '\'' + ", address='" + address + '\'' + '}';
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
@Component
public class Student {
    @Value("初尘")
    private String name;
    @Value("21")
    private int age;

    @Autowired()
    private School school;

    @Override
    public String toString () {
        return "Student{" + "name='" + name + '\'' + ", age=" + age + ", school=" + school + '}';
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

成功输出

@Autowired()注解参数中,只有一个Boolean类型的参数,

boolean required() default true;,默认就是为true,不需要写,原理就是使用自动注入的方式,使用byType或者是byName

也可以不用使用注解方式进行school对象的创建,也可以使用配置文件,进行对象的创建

<bean id="bs" class="vin.cco.anno3.School"></bean>同样也可以达到效果

使用上面这种方式进行引用赋值,是使用byType,但是如果需要使用byName,那么就需要在加上一个注解

@Qualifier("bs")
@Autowired()
private School school;
1
2
3

原理,在创建这个对象的时候,就会去寻找,对象School,并且这个对象的名字为bs的对象,如果没有找到,那么就会报错,这种方式就是通过byName进行赋值

@Component("bs")
public class School {
...
}
1
2
3
4

Autowired注解参数的使用

假如,我们使用byName进行引用的赋值操作,但是@Qualifier("bs")@Autowired()的名称写错了,如果@Autowired(required = true),那么就会报错,因为为true,就表示,会去寻找,找不到就报错

但是如果是@Autowired(required = false),当找不到的时候,就会为这个引用赋值一个null值

但是推荐使用true,因为尽管启动的时候,程序发生错误,但是我们还可以进行调试

对引用属性进行赋值,还可以使用jdk提供的注解进行@Resource,但是这个注解,在jdk11中,就不支持了

这个默认是使用byName进行注入的,但是如果使用这个名字,没有找到,就会使用byType进行赋值

# 使用配置文件和$,注解配合使用

我们也可以将参数的值,写入配置文件properties中,在注解中,使用${名称}方式进行属性的赋值操作

使用步骤

  1. 定义配置文件
  2. 在springxml文件中,加载这个配置文件
  3. 在注解中@Value("${名称})进行属性的赋值
name=chsdfuchen
age=199
1
2
<context:component-scan base-package="vin.cco.anno3" />
<!--<bean id="bs" class="vin.cco.anno3.School"></bean>-->
<context:property-placeholder location="value.properties" />
1
2
3

在注解中使用

@Value("${name}")
private String name;

@Value("${age}")
private int age;
1
2
3
4
5

成功输出,感觉使用配置文件进行传值的方式,会比较方便

# 配置文件和注解注入的选择

在使用配置文件和注解中,该如何选择呢,现在很多时候,使用的是注解的方式,但是也并不是配置文件就不行,最好的就是他们之间共同配合使用