@Autowired
和 @Resource
基本原理使用方法
@Autowired
和@Resource
注解都是作为bean对象注入的时候使用的。两者都可以声明在字段和setter方法上
public class test{
/**字段注入**/
@Autowired
private XXXService service;
/**字段注入**/
@Resource
private XXXService service;
/**构造注入**/
@Autowired
public test(XXXService service){
this.service = service;
}
/**Setter注入**/
@Autowired
public void setService(XXXService service) {
this.service = service;
}
}
以上三种使用方式 字段注入,构造注入,setter注入。
区别:
@Autowired
注解是Spring
提供的,而@Resource
注解是J2EE
本身提供的
@Autowird
注解默认通过byType
方式注入,而@Resource
注解默认通过byName
方式注入
@Autowired
注解注入的对象需要在IOC
容器中存在,否则需要加上属性required
=false
,表示忽略当前要注入的bean
,如果有直接注入,没有跳过,不会报错
其他源码不再撰述,可以自行查看网上相关资料。
不了解原理的,可以看我之前写的设计模式,策略博客:地址轻点跳转:https://blog.csdn.net/Crazy_Cw/article/details/106818217
定义一个父类接口
public interface Fruits{
void show();
}
实现接口1
//实现1
@Service
public class Apple implements Fruits {
@Override
public void show() {
System.out.println("我是苹果");
}
}
实现接口2
//实现2
@Service
public class Banana implements Fruits {
@Override
public void show() {
System.out.println("我是香蕉");
}
}
创建一个工厂,来实现不同水果
public class IndexMapDataFactory {
/**使用map,来封装**/
private static final Map<Integer, Fruits> MAP_DATA = Maps.newHashMap();
/**获得不同的实例对象**/
private static final Apple service1 = SpringUtil.getBean(Apple.class);
/**获得不同的实例对象**/
private static final Banana service2 = SpringUtil.getBean(Banana.class);
static {
MAP_DATA.put(0, service1);
MAP_DATA.put(1, service2);
}
/**获得不同的实例对象**/
public static Fruits getServiceByType(int type) {
return MAP_DATA.get(type);
}
}
我们这里看到工厂类IndexMapDataFactory
里面的不同的实现 通过手动注入, 实在不够优雅。接下来我们来升级
这里我们来把工厂类改造一下升级一下,变得更加的优雅
/**记为Spring容器中的一个Bean**/
@Slf4j
@Component
public class StrategyFactory {
/**Spring会将实现注入到该map 里面, key:注入的name,默认类名小写, value:为该实例 **/
@Resource
private Map<String, Fruits> interFaceMap;
public Fruits getServiceByType(Integer code) {
String implementName = FruitsTypeEnum.getImplementByCode(code);
Fruits bean = interFaceMap.get(implementName);
if(bean == null){
log.error("策略工厂bean异常:{} bean is null",implementName);
throw new RuntimeException("bean is null");
}
return bean;
}
public enum FruitsTypeEnum {
APPLE(1,"apple", "苹果"),
/**记为Spring容器中的一个Bean**/
BANANA(2,"banana", "香蕉"),
/**code**/
public Integer code;
/**接口的实现类名**/
public String implement;
/**备注**/
public String desc;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getImplement() {
return implement;
}
public void setImplement(String implement) {
this.implement = implement;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
FruitsTypeEnum(Integer code, String implement, String desc) {
this.code = code;
this.implement = implement;
this.desc = desc;
}
public static String getImplementByCode(Integer code) {
for (FruitsTypeEnum value : FruitsTypeEnum.values()) {
if (value.getCode().equals(code)) {
return value.getImplement();
}
}
return null;
}
}
}
使用
public void Controller {
@Resource
StrategyFactory strategyFactory;
public void test(int code){
Fruits fruits = strategyFactory.getServiceByType(code);
fruits.show();
}
}
自定义注解
import com.hong.strategy.enums.OrderTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义策略注解
*/
@Target({ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface FruitsTypeAnnotation {
/**
* 策略类型
*/
String fruitsType();
}
接口实现
//实现1
@FruitsTypeAnnotation(type = "apple")
@Service
public class Apple implements Fruits {
@Override
public void show() {
System.out.println("我是苹果");
}
}
//实现2
@FruitsTypeAnnotation(type = "banana")
@Service
public class Banana implements Fruits {
@Override
public void show() {
System.out.println("我是香蕉");
}
}
一个水果品种实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Type {
private String name;
}
向spring容器中注入
@Component
public class StrategyFactory {
private Map<String, Fruits> map;
@Autowired
public void setMap(List<Fruits> fruitsInterfaces) {
map = fruitsInterfaces.stream().collect(
Collectors.toMap(t -> AnnotationUtils.findAnnotation(t.getClass(), FruitsTypeAnnotation.class).type(),
v -> v, (v1, v2) -> v1));
}
public void fruitsService(List<Type> list){
list.forEach(t->{
//可以根据注解的值判断走哪个实现类,如果有多个实现类就会依次走
Fruits fruits = map.get(t.getName());
fruits.show();
});
}
}
测试
@Autowired
private StrategyFactory strategyFactory;
@Test
void test(){
Type apple = new Type("apple");
Type banana = new Type("banana");
strategyFactory.fruitsService(Arrays.asList(apple,banana));
}