前言:

本文内容:注解实现自动装配、Spring注解开发、使用JavaConfig实现配置

推荐免费Spring5基础教程视频:【狂神说Java】Spring5最新完整教程IDEA版通俗易懂_哔哩哔哩_bilibili

注解实现自动装配

jdk1.5支持的注解,spring2.5支持注解

要使用注解需要:

  1. 导入约束 context

  2. 配置注解支持

    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>

@Autowired注解自动注入

实体类Person.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.jokerdig.pojo;

import org.springframework.beans.factory.annotation.Autowired;

/**
* @author Joker大雄
* @data 2022/5/13 - 13:24
**/
public class Person {
// 使用注解自动注入
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;

// get/set/toString .....
// 使用@AutoWired(它的底层使用反射)后可以省略set方法
}

beans.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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:annotation-config/>

<bean id="cat" class="com.jokerdig.pojo.Cat"/>
<bean id="dog" class="com.jokerdig.pojo.Dog"/>
<bean id="person" class="com.jokerdig.pojo.Person"/>

</beans>

测试运行结果

1
2
3
4
汪汪
喵喵

Process finished with exit code 0

@Nullable注解自动注入

字段标记了这个注解,说明这个字段可以为NULL

1
2
3
4
5
6
7
8
public class Person {
// 如果显示定义required=false,则说明该对象可以为null,否则不允许为空
@AutoWired(required=false)
private Cat cat;
@Autowired
private Dog dog;
private String name;
}

如果我们自动装配环境比较复杂,自动装配无法通过一个注解(@Autowired)完成的时候,使用@Qualifier(value=xx)去配置,只当唯一的bean对象注入

Person.java

1
2
3
4
5
6
7
8
9
10
public class Person {
@Autowired
@Qualifier(value="cat1")
private Cat cat;
@Autowired
@Qualifier(value="dog1")
private Dog dog;
private String name;
// get/set/toString
}

beans2.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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:annotation-config/>


<bean id="cat1" class="com.jokerdig.pojo.Cat"/>
<bean id="cat2" class="com.jokerdig.pojo.Cat"/>
<bean id="dog1" class="com.jokerdig.pojo.Dog"/>
<bean id="dog2" class="com.jokerdig.pojo.Dog"/>
<bean id="person" class="com.jokerdig.pojo.Person"/>
</beans>

@Resource注解自动注入

Person.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.jokerdig.pojo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Resource;

/**
* @author Joker大雄
* @data 2022/5/13 - 13:24
**/
public class Person {
@Resource
private Cat cat;
@Resource(name="dog2")
private Dog dog;
private String name;

// get/set/tosting...
}

beans.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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:annotation-config/>


<bean id="cat1" class="com.jokerdig.pojo.Cat"/>
<bean id="dog1" class="com.jokerdig.pojo.Dog"/>
<bean id="dog2" class="com.jokerdig.pojo.Dog"/>
<bean id="person" class="com.jokerdig.pojo.Person"/>
</beans>

小结

@Resource和@Autowired的区别

  • 都是用来自动装配的,都可以放在属性字段上
  • @Autowired通过byType的方式实现,必须要求这个对象存在!(常用)
  • @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到,就会报错!
  • 执行顺序不同:@Autowired通过byType的方式。@Resource默认通过byName的方式实现

Spring注解开发

在Spring4之后,如果使用注解,必须导入AOP的包

使用注解需要导入context约束,增加注解的支持

新建一个Maven的Module

编写applicationContext.xml

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 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.jokerdig"/>
<!-- 注解支持-->
<context:annotation-config/>
</beans>
  1. bean

    @Component:组件,放在类上,说明这个类被Spring管理了,就是bean

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.jokerdig.pojo;

    import org.springframework.stereotype.Component;

    /**
    * @author Joker大雄
    * @data 2022/5/14 - 13:30
    **/
    // 组件
    @Component
    public class User {
    public String name="张三";

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }
    }
  2. 属性如何注入

    @value 相当于bean中的propert;也可以在set方法上

    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
    package com.jokerdig.pojo;

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

    /**
    * @author Joker大雄
    * @data 2022/5/14 - 13:30
    **/
    // 组件
    @Component
    public class User {
    // 相当于bean中的property
    @Value("张三")
    public String name;

    public String getName() {
    return name;
    }
    // 也可以在set方法上
    // @Value("张三")
    public void setName(String name) {
    this.name = name;
    }
    }
  3. 衍生的注解

    @Component有几个衍生注解,会在web开发中使用,按照MVC三层架构分层

    • dao(@Repository)

      1
      2
      3
      4
      5
      // dao层
      @Repository
      public class UserDao {
      // dao层内容...
      }
    • service(@Service)

      1
      2
      3
      4
      5
      // service层
      @Service
      public class UserService {
      // service层内容...
      }
    • controller(@Controller)

      1
      2
      3
      4
      5
      // controller层
      @Controller
      public class UserController {
      // controller层内容...
      }
  4. 自动装配配置

    @Autowired 自动装配通过类型和名字

    @Qualifier(value=xxx)不能唯一自动装配时使用

    @Nullable 标记字段允许为null

    @Resource 自动装配通过名字和类型

  5. 作用域

    @Scope

    • @Scope("singleton") 单例模式
    • @Scope("prototype") 原型模式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 组件
    @Component
    // 作用域 这里使用单例模式
    @Scope("singleton")
    public class User {
    // 相当于bean中的property
    @Value("张三")
    public String name;

    public String getName() {
    return name;
    }

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

    XML与注解

    • xml更加万能,适用于任何场合,维护简单方便
    • 注解不是自己的类使用不了,维护相对复杂

    XML与注解最佳实践:

    • xml用来管理bean
    • 注解只负责完成属性的注入

使用JavaConfig实现配置

完全不使用xml配置

  1. 新建Maven的Module

  2. 新建User.java实体类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package com.jokerdig.pojo;

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

    /**
    * @author Joker大雄
    * @data 2022/5/14 - 14:10
    **/
    @Component
    public class User {
    @Value("李四")
    private String name;

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }
    }
  3. 新建SpringConfig.java

    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
    package com.jokerdig.config;

    import com.jokerdig.pojo.User;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;

    /**
    * @author Joker大雄
    * @data 2022/5/14 - 14:09
    **/
    // 组件
    @Configuration
    // 扫描包
    @ComponentScan("com.jokerdig.pojo")
    public class SpringConfig {

    // 注册一个bean 就相当于我们之气那写的一个bean标签
    // 这个方法的名字 相当于bean标签中的id
    // 方法中的返回值 相当于bean标签中的class
    @Bean
    public User getUser(){
    return new User();
    }
    }
  4. 编写测试类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.joekrdig.test;

    import com.jokerdig.config.SpringConfig;
    import com.jokerdig.pojo.User;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;

    /**
    * @author Joker大雄
    * @data 2022/5/14 - 14:13
    **/
    public class SpringTest {
    @Test
    public void test(){
    // 读取配置的java类
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

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

    System.out.println(getUser.getName());

    }
    }
  5. 运行结果

    1
    2
    3
    李四

    Process finished with exit code 0