前言
在进行属性注入时,@Autowired
和@Resource
这两个注解经常在项目中可以看到,所以探讨下这两个注解有什么区别
相同点
接口有单一实现类时,针对接口的注入,两者可以互相替换,功能是一样的。
不同点
1、@Autowired
是Spring
中的注解。@Resource
是Java
中的注解
2、@Resource
可以指定byName
、byType
策略注入,默认是byName
,如果根据name
找不到,就会根据type
注入。
@Autowired
只能根据type
注入,如果有多个type
类型,可以配合@Qualifier
注解来根据名称注入
代码展示-@Autowired
@Autowired源码定义:
首先定义一个需要被注入的接口类型
1 2 3 4 5 6 7
| @Repository public interface UserRepository { User getUserById(Long id); void saveUser(User user); List<User> getAllUsers(); }
|
下面就演示注入UserRepository
的过程
1. @Autowired在构造函数上的使用
在构造函数上加上@Autowired
注解,Spring
就能够自动装配依赖。下面是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12
| @Service public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Autowired public UserServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; }
}
|
在上面的代码中,使用@Autowired
注解来自动装配UserRepository
类型的依赖。由于没有使用任何的限定符(Qualifier)
,Spring
会根据type
来匹配依赖关系。需要注意的是,使用构造函数注入时,不需要显式地声明依赖关系的成员变量。
2. @Autowired在方法上的使用
可以在方法上声明需要自动装配的依赖。下面是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12
| @Service public class UserServiceImpl implements UserService {
private UserRepository userRepository;
@Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; }
}
|
在上面的代码中,使用@Autowired
注解来自动装配UserRepository
类型的依赖。需要注意的是,方法名并不是固定的,可以根据自己的需要进行命名。
3. @Autowired在参数上的使用
还可以在方法参数上使用它。下面是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| javaCopy code @Service public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Autowired public UserServiceImpl(UserRepository userRepository) { this.userRepository = userRepository; }
public void setUserService(@Autowired UserService userService) { // ... }
// ... }
|
4. @Autowired在字段上的使用
在字段上使用时最常用的用法。下面是一个示例:
1 2 3 4 5 6 7 8
| @Service public class UserServiceImpl implements UserService {
@Autowired private UserRepository userRepository;
}
|
5. @Autowired在注解类型上的使用
除了在构造函数、方法、参数和字段上使用@Autowired
注解,还可以在注解类型上使用它。这样,Spring
会自动装配标记了这个注解的类。下面是一个示例:
1 2 3 4 5
| @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Autowired public @interface CurrentUser { }
|
在上面的代码中,定义了一个注解类型@CurrentUser
,并使用@Autowired
注解标记它。这意味着,当在其他类中使用了@CurrentUser
注解时,Spring
会自动装配这个依赖。下面是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Service public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
@Autowired public UserServiceImpl(UserRepository userRepository, @CurrentUser User currentUser) { this.userRepository = userRepository; }
}
|
问题
有多个类型的bean怎么办?
1 2 3 4 5 6 7 8 9 10 11
| @Repository public class UserRepositoryImpl implements UserRepository {
}
@Repository public class UserRepositoryImpl2 implements UserRepository {
}
|
如果还按照上面根据类型注入,就会出现异常
1 2 3 4 5 6 7 8
| @Service public class UserServiceImpl implements UserService {
@Autowired private UserRepository userRepository;
}
|
解决方案
1、使用@Autowired
1.1 使用@Qualifier注解
可以使用@Qualifier
注解指定需要注入的Bean
的名称。需要注意的是,这里的名称是Bean
的名称,而不是属性名或类名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Repository("userRepositoryImpl") public class UserRepositoryImpl implements UserRepository {
}
@Repository("userRepositoryImpl2") public class UserRepositoryImpl2 implements UserRepository {
}
@Service public class UserServiceImpl implements UserService {
@Autowired @Qualifier("userRepositoryImpl") private UserRepository userRepository;
}
|
1.2 使用@Primary注解
还可以使用@Primary
注解标记一个Bean
为首选Bean
。这样在自动装配时,Spring
会优先选择带有@Primary
注解的Bean
进行装配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Repository @Primary public class UserRepositoryImpl implements UserRepository {
}
@Repository public class UserRepositoryImpl2 implements UserRepository {
}
@Service public class UserServiceImpl implements UserService {
@Autowired private UserRepository userRepository;
}
|
2、使用@Resource
2.1 按类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Repository public class UserRepositoryImpl implements UserRepository {
}
@Repository public class UserRepositoryImpl2 implements UserRepository {
}
@Service public class UserServiceImpl implements UserService {
@Resource(type = UserRepositoryImpl2.class) private UserRepository userRepository;
}
|
2.2 按名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Repository("userRepositoryImpl") public class UserRepositoryImpl implements UserRepository {
}
@Repository("userRepositoryImpl2") public class UserRepositoryImpl2 implements UserRepository {
}
@Service public class UserServiceImpl implements UserService {
@Resource(name = "userRepositoryImpl2") private UserRepository userRepository;
}
|