+-
Spring容器注解注入

本节主要学习Spring容器核心DI/IOC使用注解方式进行开发。

1.组件注解

组件注解主要包括@Component,@Repository,@Service,@Controller四种。其中@Component是通用型组件,其他三个组件注解,是按照分层的思想,拆分成三个专业型组件:持久化层组件@Repository,服务层组件(业务逻辑层组件)@Service,控制层组件@Controller。

组件注解的注意事项如下:

1.四个组件注解,要放在接口的实现类上,而不是接口或抽象类

2.四个组件注解,都可以使用默认命名,也可以自定义命名,以@Component为例:

<!-- 默认bean组件名称为user --> @Component public class User { ... } <!-- 默认bean组件名称为userType --> @Component public class UserType { ... } <!-- 指定bean组件名称为user --> @Component("user") public class User { ... } <!-- 指定bean组件名称为userType --> @Component("userType") public class UserType { ... }

3.四个组件注解可以相互替换。在分层架构的系统中,推荐使用专业组件

4.当一个类不确定是哪一层代码,推荐使用通用组件注解@Component

5.注解标识的组件和配置文件中的组件是等效的,它们可以相互调用

1.1 @Component注解

此注解是泛指,标记为通用型组件,相当于spring配置文件中的<bean id="..." class="..."/>,标注在具体实现类上面。

//@Component @Component("role") public class Role { @Value("2000") private Integer id; @Value("dev") private String name; }

1.2 @Repository注解

持久化层组件注解,应用于DAO层具体实现类上,生成持久化对象。

package raky.train.dao.impl; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; import raky.train.dao.UserDao; import raky.train.entity.User; @Slf4j @Repository public class UserDaoImpl implements UserDao { @Override public int save(User user) { //模拟保存数据库 log.info("===UserDaoImpl==user====>{}",user); return 0; } }

1.3 @Service注解

服务层组件注解,应用于Service层具体实现类上,生成业务对象。

package raky.train.service.impl; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import raky.train.dao.UserDao; import raky.train.entity.User; import raky.train.service.UserService; import javax.annotation.Resource; @Slf4j @Service public class UserServiceImpl implements UserService { // @Autowired // @Qualifier("userDaoImpl") @Resource(name = "userDaoImpl") private UserDao userDao; @Override public int save(User user) { log.info("===service==user====>{}",user); return userDao.save(user); } }

1.4 @Controller注解

控制层组件注解,应用于Controller层具体实现类上,生成控制类对象。此注解一般特指用在Spring MVC的控制层组件上。

package raky.train.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import raky.train.entity.User; import raky.train.service.UserService; @Slf4j @Controller public class UserController { @Autowired private UserService userService; @Resource private User user; public int save(){ log.info("=====controller====>service : {}",userService); log.info("===controller==user====>{}",user); return userService.save(user); } }

2.注入注解

注入注解,可以自动注入spring工厂中已经创建的bean实例,无论是通过配置文件,还是组件注解生成的对象。它的作用相当于配置文件中的ref,即引用其他的bean。

@Resource和@Autowired的优先级顺序不同,另外@Resource属于 Jakarta EE规范,而@Autowired属于Spring范畴,@Resource无法使用在构造参数中,@Autowired支持required属性。从面向对象来说,@Resource更加适用于多态性的细粒度注入,而@Autowired更多专注于多态的单例注入。

2.1 @Autowired注解

此注解是Spring提供,标注在属性(字段)、setter方法、构造方法上,默认会按照类型(byType)自动装配属性或参数。该注解,可以自动装配接口的实现类,但前提是一个接口在spring容器中只有一个实现类的bean,多个bean会报错。这时需要添加@Qualifier注解,按照bean的名称匹配。

... @Autowired注解 @Component public class User { //标注在属性(字段)上 //@Autowired private Role role; //标注在构造方法上 //@Autowired public User(Role role){ this.role = role; } //标注在setter方法上 @Autowired public void setRole(Role role) { this.role = role; } }

2.2 @Resource注解

此注解属于JSR-250规范的一个注解,包含Jakarta EEJavaEE)中,spring支持该注解。使用标注在属性(字段)、setter方法上。默认情况下,按照名称注入(byName),如果没有显式声明名称则按照变量名称或者方法中对应的参数名称进行注入,也可以按照名称注入(byType)。


... @Resource注解 @Component public class User { //标注在属性(字段)上 //@Resource //@Resource(name = "role") 按照组件名称注入 //@Resource(type = Role.class) 按照组件类型注入 private Role role; //标注在setter方法上 @Resource //@Resource(name = "role") 按照组件名称注入 //@Resource(type = Role.class) 按照组件类型注入 public void setRole(Role role) { this.role = role; } }

3.其他注解

3.1 @Value注解

此注解主要是为类属性/字段赋值。

@Component public class User { @Value("1000") private Integer id; @Value("raky") private String name; //getter and setter }

3.2 @Qualifier注解

此注解主要是确定注入具体组件(多个实现选择具体组件),标注在属性或setter方法上面。

//接口 public interface UserDao { int save(User user); } //接口实现1==>保存数据库 @Repository public class UserDaoImpl implements UserDao { //... } //接口实现2==>保存成文件 @Repository public class UserDaoImpl2 implements UserDao { //... } @Service public class UserServiceImpl implements UserService { @Autowired @Qualifier("userDaoImpl") private UserDao userDao; }

3.3 @Scope注解

此注解主要标注在类或方法上面,确定工厂生成的实例对象的作用范围。取值范围主要有:

singleton 单例模式,生成一个实例/对象

prototype 原型模式,调用一次,生成一次对象

request 请求作用域(web端)

session 会话作用域(web端)

application 应用程序作用域(web端)

websocket web套接字作用域(web端)

@Scope //@Scope("singleton") @Component("role") public class Role { @Value("2000") private Integer id; @Value("dev") private String name; }

3.4 @Primary注解

此注解标注在类上面,确定优先选择具体实现对象实例。

//接口 public interface UserDao { int save(User user); } //接口实现1==>保存数据库 @Primary @Repository public class UserDaoImpl implements UserDao { //... } //接口实现2==>保存成文件 @Repository public class UserDaoImpl2 implements UserDao { //... } @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; }

3.5 @Configuration注解

此注解告诉spring容器这是一个配置类,相当于一个spring的配置文件

@Configuration==beans.xml

package raky.train.config; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import raky.train.controller.UserController; import raky.train.entity.Group; @Slf4j @Configuration @ComponentScan(basePackages = {"raky.train"}) public class AppConfig { private static ApplicationContext context; @Bean public Group getGroup(){ return new Group(1000,"king"); } public static void main(String[] args) { //通过注解配置获取spring工厂 context = new AnnotationConfigApplicationContext(AppConfig.class); Group group = context.getBean(Group.class); log.info("======>group : {}", group); } }

3.6 @Bean注解

该注解告诉 Spring,一个带有 @Bean 的注解方法将返回一个对象,该对象应该被注册为在 Spring 应用程序上下文中的 bean。给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id。

@Bean 等价于 <bean></bean>,可以给@Bean设置value来修改id,比如@Bean("userAlias")

可以在@bean中指定初始化和销毁方法,如下代码:

@Bean(value = "beanLife",initMethod = "init", destroyMethod = "destroy") //等价于 <bean id="user" class="raky.User" init-method="init" destroy-method="destroy"/>

4.注意事项

4.1 接口与实现

一个接口只有一个实现,注入注解@Autowired/@Resource没有问题,唯一实现;

一个接口有多个实现,依赖注入必须进行区分,否则会报错NoUniqueBeanDefinitionException;

第一种:指定具体名称@Resource(name = "userDaoImpl")

第二种:设置优先级 @Primary

第三种:@Autowired和@Qualifier("userDaoImpl")配合使用

4.2 组件注入/装配模式

组件装配模式,即按照什么样的方式来装配组件,在配置文件中<beans default-autowire=""></beans>进行设置,具体的值有:no 没有; default 默认注入方式;byName 按照名称注入;byType 按照类型注入;constructor 按照构造器注入。

想学习Spring容器其他注入方式,请查看我的学习笔记:《Spring容器6种注入方式》。

至此,Spring容器核心DI/IOC使用注解方式进行开发的学习笔记整理完毕。希望对大家有帮助。越分享越快乐。