Spring注解开发

本文最后更新于:1 年前

SpringIoc的使用,需要我们通过XML将类声明给Spring容器进行管理,从而通过Spring工厂完成对象的创建及属性值的注入;Spring除了提供基于XML的配置方式,同时提供了基于注解的配置:直接在实体类中添加注解声明给Spring容器管理,以简化开发步骤。

Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。

注解开发步骤

1. 添加SpringIoC依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>

2. 创建Spring配置文件

Spring容器初始化时,只会加载 applicationContext.xml 文件,我们在实体类中添加的注解就不会被Spring扫描,所以我们需要applicationContext.xml 中声明Spring的扫描范围,以达到Spring初始化时扫描带有注解的实体类并完成初始化工作。

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
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 声明使用注解配置 -->
<context:annotation-config/>

<!-- 声明Spring工厂注解的扫描范围 -->
<context:component-scan base-package="cc.gaojie.beans"/>

</beans>

3. 使用Spring注解开发

Spring原始注解

Spring原始注解主要是替代 <Bean> 的配置。

注解 说明
@Component 使用在类上用于实例化Bean
@Controller 使用在web层类上用于实例化Bean
@Service 使用在service层类上用于实例化Bean
@Repository 使用在dao层类上用于实例化Bean
@Autowired 使用在字段上用于根据类型依赖注入
@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Resource 相当于@Autowired+ @Qualifier,按照名称进行注入
@Value 注入普通属性
@Scope 标注Bean的作用范围
@PostConstruct 使用在方法上标注该方法是Bean的初始化方法
@PreDestroy 使用在方法上标注该方法是Bean的销毁方法

@Component

  • 类注解,声明此类被Spring容器进行管理,相当于bean标签的作用。

  • @Component(value="stu") value属性用于指定当前bean的id,相当于bean标签的id属性;value属性也可以省略,如果省略当前类的id默认为类名首字母改小写。

  • 除了@Component之外 @Service、@Controller、@Repository这三个注解也可以将类声明给Spring管理,他们主要是语义上的区别:

    • @Controller 注解主要声明将控制器类配置给Spring管理,例如Servlet。
    • @Service 注解主要声明业务处理类配置Spring管理,Service接口的实现类。
    • @Repository 直接主要声明持久化类配置给Spring管理,DAO接口。

    除了控制器、servcie和DAO之外的类一律使用 @Component 注解来声明。


  1. 创建实体类并用 @Component 注解来声明

    Student.java
  2. applicationContext.xml 中声明Spring的扫描范围

    1
    2
    3
    4
    5
    <!-- 声明使用注解配置 -->
    <context:annotation-config/>

    <!-- 声明Spring工厂注解的扫描范围 -->
    <context:component-scan base-package="cc.gaojie.beans"/>
  3. 通过Spring工厂获取Student对象

    Test.java

@Scope

  • 类注解,用于声明当前类为单例模式还是非单例模式,相当于bean标签的scope属性。
  • @Scope("prototype") 表示声明当前类为非单例模式(默认单例模式)。

@Lazy

  • 类注解,用于声明一个单例模式的Bean是否为懒汉模式
  • @Lazy(true) 表示声明为懒汉模式,默认为饿汉模式

饿汉模式

懒汉模式

@PostConstruct

方法注解,声明一个方法为当前类的初始化方法(在构造器之后执行),相当于bean标签的init-method属性。

@PreDestroy

方法注解,声明一个方法为当前类的销毁方法(在对象从容器中释放之前执行),相当于bean标签的destory-method属性

@Autowired

  • 属性注解,声明当前属性自动装配,默认是 byType 。

  • @Autowired(required = false) 通过requried属性设置当前自动装配是否为必须(默认为必须,如果没有找到类型与属性类型匹配的bean则抛出异常)

  • 方法注解,用在set方法之前,requried属性默认为必须,自动装配时默认是 byType ,可使用 @Qualifier 注解指定为通过ref引用匹配。

    • byType匹配

    • ref引用匹配

@Resource

  • 属性注解,也用于声明属性自动装配。
  • 默认装配方式为 byName,如果根据byName没有找到对应的bean,则会继续根据byType寻找对应的bean,如果根据byType依然没有找到Bean或者找到不止一个类型匹配的bean,则抛出异常。

原始注解使用案例

  1. 配置注解的组件扫描

    使用注解进行开发时,需要在 applicationContext.xml 中配置组件扫描,作用是指定哪个包及其子包下的 Bean 需要进行扫描以便识别使用注解配置的类、字段和方法。

    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 http://www.springframework.org/schema/context/spring-context.xsd">

    <!--加载外部的properties文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置组件扫描-->
    <context:component-scan base-package="cc.gaojie"/>

    </beans>
  2. 使用 @Compont@Repository 标识 UserDaoImpl 需要 Spring 进行实例化。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /*<bean id="userDao" class="cc.gaojie.dao.impl.UserDaoImpl" ></bean>*/
    //@Component("userDao")
    @Repository("userDao")
    public class UserDaoImpl implements UserDao {

    @Override
    public void save() {
    System.out.println("sava running…………");
    }
    }
  3. 使用 @Autowired 或者 @Autowired+@Qulifier 或者 @Resource 进行 userDao 的注入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /*<bean id="userService" class="cc.gaojie.service.impl.UserServiceImpl">*/
    //@Component("userService")
    @Service("userService")
    public class UserServiceImpl implements UserService {

    /*<property name="userDao" ref="userDao"></property>*/
    @Autowired //按数据类型从Spring容器中进行匹配,但容器有多个UserDao类型bean会报错
    @Qualifier("userDao") //按照 id 的值从Spring容器中匹配,必须结合@Autowired使用
    //@Resource(name = "userDao") //相当于@Qualifier+@Autowired
    private UserDao userDao;

    @Override
    public void save() {
    userDao.save();
    }
    }
  4. 模拟 web 层测试

  5. 使用 @Scope 标注Bean的作用范围, @Value注入普通属性; @PostConstruct@PreDestroy标注bean的初始化与销毁方法

    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
    28
    29
    30
    31
    32
    33
    @Service("userService")
    @Scope("singleton") //标注bean的作用范围
    public class UserServiceImpl implements UserService {

    //注入普通属性
    //@Value("com.mysql.jdbc.Driver") //等同于直接赋值
    @Value("${jdbc.driver}") //匹配配置文件中的键的值
    private String driver;

    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
    }

    @Override
    public void save() {
    userDao.save();
    System.out.println(driver);
    }

    @PostConstruct //标注bean的初始化方法(构造之后)
    public void init() {
    System.out.println("Service对象的初始化方法");
    }

    @PreDestroy //标注bean的销毁方法
    public void destroy() {
    System.out.println("Service对象的销毁方法");
    }
    }

Spring新注解

使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:

  • 非自定义的Bean的配置:<bean>
  • 加载properties文件的配置:<context:property-placeholder>
  • 组件扫描的配置:<context:component-scan>
  • 引入其他文件:<import>
新注解 说明
@Configuration 用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan 用于指定 Spring 在初始化容器时要扫描的包。
作用和在 Spring 的 xml 配置文件中的
<context:component-scan base-package=”com.itheima”/>一样
@Bean 使用在方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource 用于加载.properties 文件中的配置
@Import 用于导入其他配置类
  1. 创建 Spring 核心配置类,代替之前的 xml 文件
1
2
3
4
5
6
7
8
9
//标准该类是Spring核心配置类,代替之前的xml文件
@Configuration
//<context:component-scan base-package="cc.gaojie"/>
@ComponentScan("cc.gaojie") //代替上面的组件扫描
//<import resource="applicationContext-goods.xml"/>
@Import(DataSourceConfiguration.class) //加载数据源配置,加载多个用,分隔
public class SpringConfiguration {

}
  1. 数据集相关配置类

    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
    //<context:property-placeholder location="classpath:jdbc.properties"/>
    @PropertySource("classpath:jdbc.properties") //加载外部配置文件
    public class DataSourceConfiguration {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    //Spring会将当前方法的返回值以指定名称存储到容器中
    @Bean("dataSource")
    public DataSource getDataSource() throws PropertyVetoException {
    //创建数据源实例
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    //设置数据源连接参数
    dataSource.setDriverClass(driver);
    dataSource.setJdbcUrl(url);
    dataSource.setUser(username);
    dataSource.setPassword(password);
    return dataSource;
    }

    }
  2. 测试加载核心配置类创建Spring容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class UserController {

    public static void main(String[] args) {
    //ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
    UserService userService = app.getBean(UserService.class);
    userService.save();

    }
    }


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!