Spring中使用注解开发

1 什么是注解开发?

在 Spring 中提供了丰富的注解来替代之前的 xml 配置文件。注解开发能极大的提高我们开发的效率。但是其底层使用的其实还是 xml 配置的方式,注解不过是简化了开发

2 使用配置类替代配置文件

(1)配置类

java 复制代码
/**
 * 配置类,代替xml配置文件
 * Configuration 声明这是配置类
 * ComponentScan 代替xml中使用标签配置包扫描的范围
 * PropertySource 添加配置文件,方便写入参数,最好前面使用 classpath
 *
 */
@Configuration
@ComponentScan("cn.edu.njust")
//@PropertySource("jdbc.properties")
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
}
  • 有了这个类,我们就可以直接删掉applicationContext.xml文件;
  • 之后会使用这个配置类来加载 Spring 的上下文信息;

(2)使用配置类来获取 IoC 容器

java 复制代码
/**
 * 使用配置类代替配置文件
 */
public class TestDemo03 {
    public static void main(String[] args) {
        // 加载配置类获取IoC容器对象
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserDao userDao1 = ctx.getBean("userDao", UserDao.class);
        userDao1.run();
    }
}

3 使用注解管理 bean 对象

相比于使用 xml 文件配置 bean 对象,使用注解配置 bean 对象更加的方便;

3.1 将一个类声明为 bean 对象

(1)@Component:一个很通用的注解,有这个注解声明的类,IoC 容器就可以对其 bean 对象进行管理;一般情况下,如果某个类不知道其所属的层,如持久层、服务层或者控制层,但是又希望将其 bean 对象交给 IoC 容器管理,就可以使用这个注解。

(2)@Repository:持久层注解,一个类被这个注解声明,表示这个类是位于持久层,对数据库进行操作;

(3)@Service:服务层注解,该声明表示这个类位于服务处,一般会涉及较为复杂的业务逻辑,同时,这个中通常会使用到持久层的 bean 对象;

(4)@Controller:控制层注解,该声明表示这个类是控制层的,在 SpringMVC 中,这个层交给 SpringMVC 的上下文管理,主要是负责接收前端的请求,并且将调用 Service 层的业务,完成处理后将信息返回给前端。这个层中会使用到服务处的 bean 对象;

(5)说明:@Repository、@Service、@Controller 这三个注解都是对@Component 注解的封装。

3.2 @Component 替换 bean 标签

直接在相应的实现类上使用 @Component 注解,即可将该类的实现类放松 IoC 容器中进行 bean 管理。

java 复制代码
/**
 * Component: 就是声明一个 bean,id为 userDao
 */
@Component("userDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void run() {
        System.out.println("UserDao is running...");
    }
}
  • 其他的几个注解使用方式类似

4 依赖注入

4.1 按名称依赖注入

单独使用 Autowired,默认是按类型自动配置,但是当 IoC 容器中有多个同类型的 bean 对象的时,会出现问题,解决方法是使用按名称自动配置的方式,即在多个 bean 对象使用@Component 注解的时候,后面指定名称,然后使用@Qualifier 指定具体是哪个类。

(1)@Autowired 声明在变量上

java 复制代码
package cn.edu.njust.service.impl;

import cn.edu.njust.dao.UserDao;
import cn.edu.njust.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("userService")
public class UserServiceImpl implements UserService {
    /*
    * Autowired 直接作用在成员变量上
    * 直接作用在成员变量类型上是因为底层使用的是暴力反射的机制
    * */
    @Autowired
    private UserDao userDao;
    @Override
    public void run() {
        System.out.println("UerService is running...");
        userDao.run();
    }
}
  • 注解直接声明在变量上,是因为 Spring 底层使用的是暴力反射,所以可以直接获取变量赋值
  • 这样的方式是属于按名称自动配置的;

(2)@Autowired 声明在 setter 上

java 复制代码
package cn.edu.njust.service.impl;

import cn.edu.njust.dao.UserDao;
import cn.edu.njust.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("userService")
public class UserServiceImpl implements UserService {
    /*
    * Autowired 直接作用在成员变量上
    * 直接作用在成员变量类型上是因为底层使用的是暴力反射的机制
    * 可以直接获取到这个属性赋值,不需要使用setter
    * 当然作用在setter上也是没有问题的
    * */
    private UserDao userDao;
    
    @Override
    public void run() {
        System.out.println("UerService is running...");
        userDao.run();
    }

    /**
     * Autowired 注解可以放在setter方法上
     * @param userDao
     */
   @Autowired
   public void setUserDao(UserDao userDao) {
       this.userDao = userDao;
   }
}

4.2 按名称自动配置

同比 xml 配置的方式,也可以使用按名称自动配置,需要使用@Qualifier注解配合

java 复制代码
package cn.edu.njust.service.impl;

import cn.edu.njust.dao.UserDao;
import cn.edu.njust.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("userService")
public class UserServiceImpl implements UserService {
    /*
    * Autowired 直接作用在成员变量上
    * 直接作用在成员变量类型上是因为底层使用的是暴力反射的机制
    * 可以直接获取到这个属性赋值,不需要使用setter
    * 当然作用在setter上也是没有问题的
    * */
    @Autowired
    @Qualifier("userDao2")
    private UserDao userDao;
    
    @Override
    public void run() {
        System.out.println("UerService is running...");
        userDao.run();
    }
}
  • Autowired:指明自动配置
  • Qualifier:表明按名称自动配置,在括号内使指明 bean 对象的名称;

4.3 简单数据类型的注入

java 复制代码
@Component
public class DataSourceServiceImpl implements DataSourceService {

    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
    @Override
    public void run() {
        System.out.println("username = " + username + "&password = " + password);
    }
}

@Value(" j d b c . u s e r n a m e " ) 中, {jdbc.username}")中, jdbc.username")中,{}表示引用配置文件中的某数据

4.4 配置第三方 Bean

4.4.1 在 Spring 的配置文件中配置

java 复制代码
package cn.edu.njust.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * 配置类,代替xml配置文件
 * Configuration 声明这是配置类
 * ComponentScan 代替xml中使用标签配置包扫描的范围
 * PropertySource 添加配置文件,方便写入参数,最好前面使用 classpath
 *
 */
@Configuration
@ComponentScan("cn.edu.njust")
// @PropertySource("jdbc.properties")
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
   
    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring_db");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }
}

这种方式简单粗暴,但是不推荐,原因是如果需要配置大量的第三方 bean,会照成配置类混乱;


4.4.2 额外声明配置类

(1)直接声明为配置类

java 复制代码
package cn.edu.njust.config;

import cn.edu.njust.dao.UserDao;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * 专门配置数据源的配置类
 * 有两种方式可以让这个文件正常加载
 *      1)Configuration: 直接将其声明为配置类,在整个项目的配置文件中可以扫描到该类即可
 *      2)删除Configuration: 在配置类中使用 Import 注解引入这个配置类
 */

@Configuration
public class JDBCConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 第三方Bean中使用到其他的bean对象,做法是将该bean对象使用注解放在IoC容器中
     *
     * @param userDao 使用到的bean对象,直接用参数的形式传递进入即可
     * @return
     */
    @Bean
    public DataSource dataSource(UserDao userDao) {
        System.out.println(userDao);
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

说明:

1)方法的返回值类型就是所配置的 Bean 对象;

2)new 对象的时候接收变量不能使用 DataSource,因为 DataSource 本身是没有 setter 的;

3)方法的形参传入的是需要使用到的 bean,只要这个 bean 已经被 IoC 容器接管了,就不需要做额外的操作,使用形参传入即可。


(2)不声明为配置类,在 Spring 的配置文件中导入配置类

java 复制代码
package cn.edu.njust.config;

import cn.edu.njust.dao.UserDao;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * 专门配置数据源的配置类
 * 有两种方式可以让这个文件正常加载
 *      1)Configuration: 直接将其声明为配置类,在整个项目的配置文件中可以扫描到该类即可
 *      2)删除Configuration: 在配置类中使用 Import 注解引入这个配置类
 */
public class JDBCConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 第三方Bean中使用到其他的bean对象,做法是将该bean对象使用注解放在IoC容器中
     *
     * @param userDao 使用到的bean对象,直接用参数的形式传递进入即可
     * @return
     */
    @Bean
    public DataSource dataSource(UserDao userDao) {
        System.out.println(userDao);
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}
java 复制代码
package cn.edu.njust.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;

@Configuration
@ComponentScan("cn.edu.njust")
@PropertySource("classpath:jdbc.properties")
@Import({JDBCConfig.class})
public class SpringConfig {
}
  • 在配置类中导入@Import({JDBCConfig.class})

4.5 和第三方整合相关

1)测试要导入

xml 复制代码
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>

2)MyBatis 需要导入

xml 复制代码
<!--Spring操作数据库需要该jar包-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>
<dependency>
  <!--
  Spring与Mybatis整合的jar包
  这个jar包mybatis在前面,是Mybatis提供的
  -->
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.3.0</version>
</dependency>

6 注解汇总

**注解 ** 作用说明
@Component 将该类交给 IoC 容器管理,即可得到 bean 对象
@Controller 控制层注解,作用和@Component 相同,不过是专用于控制层
@Service 业务层注解,作用和@Component 相同,不过是专用于业务层
@Repository 持久层注解,作用和@Component 相同,不过是专用于持久层
@Configuration 配置类,配置文件专用
@ComponentScan 配置类扫描路径,效果等同于 xml 中的 context:component-scan
@PropertySource 添加在配置类中,指明配置文件,加载配置文件
@Scope 设置 bean 是否是单例,赋值 single 为单例,赋值 prototype 为非单例
@PostConstruct 在构造方法执行后执行的方法
@PreDestroy 标识在销毁之前执行的方法
@Autowired 声明在一个为赋值的成员变量上,意为自动配置,默认是按类型配置,如果同一类型的 bean 有多个,将会出错。
@Qualifier 当同一类型的 bean 有多个时,可以使用该注解配合@Autowired 实现按名称配置
@Value 简单数据类型的配置,直接声明在变量上方进行赋值
@Bean 用于管理第三方 bean,声明在一个方法上,可以将该 bean 交给 IoC 管理
@Import 声明在配置类中,可以引入多个配置类
@RunWith 设置类运行器
@ContextConfiguration 在测试类中,设置Spring环境对应的配置类
@Test 声明该方法是一个测试方法
相关推荐
程序猿零零漆22 分钟前
SpringCloud系列教程:微服务的未来(二十)Seata快速入门、部署TC服务、微服务集成Seata
java·spring·spring cloud·微服务
Miketutu10 小时前
Spring MVC消息转换器
java·spring
小小虫码12 小时前
项目中用的网关Gateway及SpringCloud
spring·spring cloud·gateway
带刺的坐椅17 小时前
无耳科技 Solon v3.0.7 发布(2025农历新年版)
java·spring·mvc·solon·aop
精通HelloWorld!20 小时前
使用HttpClient和HttpRequest发送HTTP请求
java·spring boot·网络协议·spring·http
LUCIAZZZ21 小时前
基于Docker以KRaft模式快速部署Kafka
java·运维·spring·docker·容器·kafka
拾忆,想起21 小时前
如何选择Spring AOP的动态代理?JDK与CGLIB的适用场景
spring boot·后端·spring·spring cloud·微服务
鱼骨不是鱼翅1 天前
Spring Web MVC基础第一篇
前端·spring·mvc
hong_zc1 天前
Spring MVC (三) —— 实战演练
java·spring·mvc
Future_yzx1 天前
Spring AOP 入门教程:基础概念与实现
java·开发语言·spring