在 Spring 中提供了丰富的注解来替代之前的 xml 配置文件。注解开发能极大的提高我们开发的效率。但是其底层使用的其实还是 xml 配置的方式,注解不过是简化了开发。
(1)配置类
/**
* 配置类,代替xml配置文件
* Configuration 声明这是配置类
* ComponentScan 代替xml中使用标签配置包扫描的范围
* PropertySource 添加配置文件,方便写入参数,最好前面使用 classpath
*
*/
@Configuration
@ComponentScan("cn.edu.njust")
//@PropertySource("jdbc.properties")
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
}
applicationContext.xml
文件;(2)使用配置类来获取 IoC 容器
/**
* 使用配置类代替配置文件
*/
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();
}
}
相比于使用 xml 文件配置 bean 对象,使用注解配置 bean 对象更加的方便;
(1)@Component
:一个很通用的注解,有这个注解声明的类,IoC 容器就可以对其 bean 对象进行管理;一般情况下,如果某个类不知道其所属的层,如持久层、服务层或者控制层,但是又希望将其 bean 对象交给 IoC 容器管理,就可以使用这个注解。
(2)@Repository
:持久层注解,一个类被这个注解声明,表示这个类是位于持久层,对数据库进行操作;
(3)@Service
:服务层注解,该声明表示这个类位于服务处,一般会涉及较为复杂的业务逻辑,同时,这个中通常会使用到持久层的 bean 对象;
(4)@Controller
:控制层注解,该声明表示这个类是控制层的,在 SpringMVC 中,这个层交给 SpringMVC 的上下文管理,主要是负责接收前端的请求,并且将调用 Service 层的业务,完成处理后将信息返回给前端。这个层中会使用到服务处的 bean 对象;
(5)说明:@Repository、@Service、@Controller 这三个注解都是对@Component 注解的封装。
直接在相应的实现类上使用 @Component 注解,即可将该类的实现类放松 IoC 容器中进行 bean 管理。
/**
* Component: 就是声明一个 bean,id为 userDao
*/
@Component("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void run() {
System.out.println("UserDao is running...");
}
}
单独使用 Autowired,默认是按类型自动配置,但是当 IoC 容器中有多个同类型的 bean 对象的时,会出现问题,解决方法是使用按名称自动配置的方式,即在多个 bean 对象使用@Component 注解的时候,后面指定名称,然后使用@Qualifier 指定具体是哪个类。
(1)@Autowired 声明在变量上
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();
}
}
(2)@Autowired 声明在 setter 上
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;
}
}
同比 xml 配置的方式,也可以使用按名称自动配置,需要使用@Qualifier
注解配合
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();
}
}
@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")中,{}表示引用配置文件中的某数据
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,会照成配置类混乱;
(1)直接声明为配置类
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 的配置文件中导入配置类
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;
}
}
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})
;1)测试要导入
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.2.10.RELEASEversion>
dependency>
2)MyBatis 需要导入
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.10.RELEASEversion>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>1.3.0version>
dependency>
**注解 ** | 作用说明 |
---|---|
@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 | 声明该方法是一个测试方法 |