Spring-05-注解开发

Spring-05-注解开发

mark

1. Autowired(被注入的属性)

mark

说明:

  • jdk1.5开始支持注解,spring2.5开始全面支持注解。
  • 准备工作:利用注解的方式注入属性。

mark

  1. spring配置文件中引入context文件头
1
2
3
4
xmlns:context="http://www.springframework.org/schema/context"

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
  1. 开启注解支持
1
<context:annotation-config/>

小结 : 总的模板

1
2
3
4
5
6
7
8
9
10
11
12
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

<context:annotation-config/>

</beans>

1.1 @AutoWired

AutoWired 的使用方式

  1. 使用构造器注入

mark

  1. 使用setter方法注入

mark

  1. 多个参数的方法上注入

mark

  1. 放在属性字段上注入

mark

  • @Autowired是按类型自动转配的,不支持id匹配。
  • 需要导入 spring-aop的包!
  • 使用@Autowired 我们可以不用编写 set 方法了,前提是你这个自动装配的 bean 已经在 IOC 容器中注册过了并且符合byname 名称的要求。
  • Autowired 修饰的字段是属于被注入的对象,前提必须需要注入的bean已经在ioc容器中存在(重要的话再说一次!!!)

案例快速使用

  1. 使用@Autowired注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class User {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String str;

public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getStr() {
return str;
}
}
  1. 此时配置文件的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">


<!--开启注解的支持-->
<context:annotation-config/>

<bean id="dog" class="com.zhuuu.pojo.Dog"/>
<bean id="cat" class="com.zhuuu.pojo.Cat"/>
<bean id="people" class="com.zhuuu.pojo.People"/>


</beans>
  1. 测试,成功输出结果!
1
2
3
4
5
6
7
8
9
public class MyTest {
@Test
public void testMethodAutowire() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.getCat().shout();
user.getDog().shout();
}
}

注意事项

@Autowired(required=false)

  • false 说明对象可以是null
  • true说明不能为null

其他数据对象(数据类型)

  1. 数组使用注解注入

mark

  1. 集合使用注解注入

mark

  1. 使用Map 进行注入

mark

特殊注入: 允许对象为空

  1. @Autowired(required = false)
1
2
3
4
5
6
7
8
9
10
11
public class SimpleMovieLister {

private MovieFinder movieFinder;

@Autowired(required = false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}

// ...
}
  1. @Nullable

mark

注意事项 : 数据类型的注入顺序

mark

1.2 @Qualifiers

  • @Autowired是根据类型自动装配的,加上@Qualifiers就可以根据byName方法自动装配
  • @Qualifier不能单独使用。

测试步骤

  1. 配置文件修改内容,保证类型存在对象。且名字不为类的默认名字!
1
2
3
4
<bean id="dog1" class="com.zhuuu.pojo.Dog"/>
<bean id="dog2" class="com.zhuuu.pojo.Dog"/>
<bean id="cat1" class="com.zhuuu.pojo.Cat"/>
<bean id="cat2" class="com.zhuuu.pojo.Cat"/>
  1. 没有加Qualifier测试,直接报错
  2. 在属性上添加Qualifier注解
1
2
3
4
5
6
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;

1.3 @Resource(更智能)

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配(与@Autowired是相反的);
  • 其次再进行默认的byName方式进行装配;
  • 如果以上都不成功,则按byType的方式自动装配。
  • 都不成功,则报异常

注意 : 这个注解是Java 自带的

  1. 实体类
1
2
3
4
5
6
7
8
public class User {
//如果允许对象为null,设置required = false,默认为true
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
private String str;
}
  1. applicaionContext.xml
1
2
3
4
5
<bean id="dog" class="com.zhuuu.pojo.Dog"/>
<bean id="cat1" class="com.zhuuu.pojo.Cat"/>
<bean id="cat2" class="com.zhuuu.pojo.Cat"/>

<bean id="user" class="com.zhuuu.pojo.User"/>

测试:结果OK

测试案例2

  1. 配置文件2:beans.xml , 删掉cat2
1
2
<bean id="dog" class="com.zhuuu.pojo.Dog"/> 按照id查找
<bean id="cat1" class="com.zhuuu.pojo.Cat"/> 按照type查找
  1. 实体类上只保留注解
1
2
3
4
@Resource
private Cat cat;
@Resource
private Dog dog;

结果:OK

1.4 小结

@Autowired@Resource异同:

  • @Autowired@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
  • @Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用
  • @Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
  • 它们的作用相同都是用注解方式注入对象,但执行顺序不同。
    • @Autowired先byType,
    • @Resource先byName。

正式使用注解开发

0. 前言

  • 平时开发时,并不会把东西写入xml中,多数的情况下是使用注解开发

  • 注解开发关注的方面

    • bean的注入(@Bean,@Component,@Service...)
    • 属性的注入 (@Value,@Autowired
    • xml的省略写法(@Configuration
  • spring4之后,想要使用注解形式,必须得要引入aop的包

mark

  • 在配置文件当中,还得要引入一个context约束
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">


<!--开启注解的支持-->
<context:annotation-config/>

</beans>

特别注意:

  • 上述所有内容都是为了实现正常开发使用注解的前奏铺垫
  • 以下内容才是真正使用注解开发的落地实现

1. 扫描包(不用在xml中配置Bean)

mark

  • 我们之前都是使用 bean 的标签进行bean注入,但是实际开发中,我们一般都会使用注解!
  • 这就是Bean的实例化(不用配置xml)
  1. 配置扫描哪些包下的注解
1
2
<!--扫描包-->
<context:component-scan base-package="com.zhuuu"/>
  1. 在指定包下编写类,增加注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.zhuuu.pojo;

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

// 这个@Component 注解等价于 写了一行xml代码 <bean id = "user" class = "pojo.User"/>
@Component
public class User {
public String name = "朱酱酱";

public User() {
}
}
  1. 测试(使用的bean的 id 是类名的小写)
1
2
3
4
5
6
7
8
9
10
11
import com.zhuuu.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user.name);
}
}

注意 :

mark

2. 属性注入(property 注入)

  • 使用注解注入属性(property name = “” …)
  1. 可以不使用Set方法,直接在属性上增加@Value("值")
1
2
3
4
5
6
7
@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
@Value("朱酱酱")
// 相当于配置文件中 <property name="name" value="朱酱酱"/>
public String name;
}
  1. 如果提供了set方法,在set方法上添加@value("值");
1
2
3
4
5
6
7
8
9
10
@Component("user")
public class User {

public String name;

@Value("朱酱酱")
public void setName(String name) {
this.name = name;
}
}

3. 衍生注解(MVC 三层分类)

mark

@Component三个衍生注解

为了更好的进行分层,Spring可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。

  • @Controller:web层
  • @Service:service层
  • @Repository:dao层

写上这些注解,就相当于将这个类交给Spring管理装配了

重要说明

  • @Controller:web层
  • @Service:service层
  • @Repository:dao层
  • 这三个注解本质作用就是为了不写 <bean id = xxx class = "xxx">
  • 并且这四个注解的功能是一模一样的

4. 自动装配Bean(@Autowired)

  • 见上
  • 前提是你这个注入的属性在ioc容器中已经存在

5. 作用域(@Scope)

@scope

  • singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
  • prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
1
2
3
4
5
6
7
8
9
10
// 等价于在applicationContext.xml写了一个bean
@Component
// 作用域
@Scope("singleton")

public class User {

@Value("朱酱酱")
public String name;
}

6. 小结

XML与注解比较

  • XML可以适用任何场景 ,结构清晰,维护方便
  • 注解不是自己提供的类使用不了,开发简单方便,但是有局限性
  • SpringBoot 目前项目多用注解去做

最佳配合

  • xml管理bean
  • 注解完成属性的注入
  • 使用过程中,只需要注意一个问题,要让注解生效 :开启注解支持/ 扫描包
1
<context:annotation-config/>

作用:

  • 进行注解驱动注册,从而使注解生效
  • 用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册
  • 如果不扫描包,就需要手动配置bean
  • 如果不加注解驱动,则注入的值为null

7. 基于Java类进行配置(非常重要)

官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-java

  • JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供Bean 的定义信息,在 Spring4的版本,JavaConfig已正式成为Spring4 的核心功能 。

mark

注意:这个作用就可以完全避免配置applicationContext.xml

  1. 编写一个实体类User(本质就是一个Bean)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 本质就是一个Bean
@Component
public class User {
@Value("朱酱酱")
private String name;

public String getName() {
return name;
}

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

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
  1. 新建一个config包,编写一个MyConfig配置类(相当于是一个beans(applicationContext.xml))
  • 方法名getUser() 相当于 = id
  • 返回值 User() 相当于 = class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 相当于是一个beans(applicationContext.xml)
@Configuration
@ComponentScan("com.zhuuu.pojo")
//@Import()
public class MyConfig {

// 注册一个bean(就相当于之前xml中写的一个bean)
// 方法名:对应id
// 返回值:相当于bean标签中的class属性
@Bean
public User getUser(){
return new User();
}
}
  1. 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import com.zhuuu.config.MyConfig;
import com.zhuuu.pojo.User;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Mytest {
public static void main(String[] args) {
// 这里完全使用了配置类去做
// 我们通过AnnotationConfig上下文来获取容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);;

User user = (User) context.getBean("getUser");

// 方法名就是Bean的名字
System.out.println(user.getName());
}
}

4. 测试方法二:使用无参构造器

mark

  1. 扫描包

mark

那么问题来了???

导入其他xml配置如何做呢?

  1. 我们再编写一个配置类!
1
2
3
@Configuration  //代表这是一个配置类
public class MyConfig2 {
}
  1. 在之前的配置类中我们来选择导入这个配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
//导入合并其他配置类,类似于配置文件中的 inculde 标签
@Import(MyConfig2.class)
public class MyConfig {

// 注册一个bean(就相当于之前xml中写的一个bean)
// 方法名:对应id
// 返回值:相当于bean标签中的class属性
@Bean
public User getUser(){
return new User();
}
}
  • @Configuration

    • 方法名 : bean id = xxx
    • 返回值: class = xxx
  • 关于这种Java类的配置方式,我们在之后的SpringBootSpringCloud中还会大量看到,我们需要知道这些注解的作用即可!

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信