# 使用注解前提
如果需要使用注解的方式,那么就必须要用到 spring=aop
这个包,否则的话,不能使用注解,但是使用maven,导入spring-context
依赖的时候,就会自动导入这个包
# 使用
# 步骤
- 加入maven依赖,spring-context,在加入这个依赖的时候,会间接的加入spring-aop依赖,这个依赖是注解必须的
- 在类中使用spring注解,有多个不同功能的注解
- 在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
使用注解
在这个类的上,加上
@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" />
创建组件扫描器
如果使用了注解之后,一定要使用组件扫描器,需要创建一个配置文件
<context:component-scan base-package="vin.cco.domain" />
其中,
base-package="vin.cco.domain"
这个是一个包名路径,不是类的全限定名称其工作原理是,添加了这个标签之后,spring就会自动扫描这个包中,和子包中的所有的类,会在这些类中寻找有这个注解的类,如果有,则会创建对象,或者是给属性赋值
加入这个组件扫描器之后,配置文件会有什么变化
- 会自动的加上一个约束文件(idea会自动加上)
- 给约束文件,起一个别名空间
最初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 + '}';
}
}
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);
}
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 + '\'' + '}';
}
}
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 + '}';
}
}
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;
2
3
原理,在创建这个对象的时候,就会去寻找,对象School,并且这个对象的名字为bs的对象,如果没有找到,那么就会报错,这种方式就是通过byName进行赋值
@Component("bs")
public class School {
...
}
2
3
4
Autowired
注解参数的使用
假如,我们使用byName进行引用的赋值操作,但是@Qualifier("bs")@Autowired()
的名称写错了,如果@Autowired(required = true)
,那么就会报错,因为为true,就表示,会去寻找,找不到就报错
但是如果是@Autowired(required = false)
,当找不到的时候,就会为这个引用赋值一个null值
但是推荐使用true,因为尽管启动的时候,程序发生错误,但是我们还可以进行调试
对引用属性进行赋值,还可以使用jdk提供的注解进行@Resource
,但是这个注解,在jdk11中,就不支持了
这个默认是使用byName进行注入的,但是如果使用这个名字,没有找到,就会使用byType进行赋值
# 使用配置文件和$,注解配合使用
我们也可以将参数的值,写入配置文件properties中,在注解中,使用${名称}方式进行属性的赋值操作
使用步骤
- 定义配置文件
- 在springxml文件中,加载这个配置文件
- 在注解中
@Value("${名称})
进行属性的赋值
name=chsdfuchen
age=199
2
<context:component-scan base-package="vin.cco.anno3" />
<!--<bean id="bs" class="vin.cco.anno3.School"></bean>-->
<context:property-placeholder location="value.properties" />
2
3
在注解中使用
@Value("${name}")
private String name;
@Value("${age}")
private int age;
2
3
4
5
成功输出,感觉使用配置文件进行传值的方式,会比较方便
# 配置文件和注解注入的选择
在使用配置文件和注解中,该如何选择呢,现在很多时候,使用的是注解的方式,但是也并不是配置文件就不行,最好的就是他们之间共同配合使用