【每天学点Spring】

【每天学点Spring】@Autowired,@Inject,@

2022-04-15  本文已影响0人  伊丽莎白2015

@Autowired,@Inject,@Resource提供的功能都比较类似,都能实现依赖注入。但也有些许不同。

文章内容:

Inject Annotation.jpg

@Autowired

@Autowired是Spring提供的注解:

首先是按type匹配,UserService只有一个实现类,所以注入成功!

public interface UserService {
    String getName();
}

@Service
public class DoctorUserServiceImpl implements UserService {
    public String getName() {
        return "DoctorUserServiceImpl";
    }
}

@SpringBootTest
public class UserServiceTest {
    @Autowired
    private UserService userService;

    @Test
    public void test() {
        System.out.println(userService.getName()); // 打印结果:DoctorUserServiceImpl
    }
}

如果此时UserService又多了一个实现类TeacherUserServiceImpl

@Service
public class TeacherUserServiceImpl implements UserService {
    public String getName() {
        return "TeacherUserServiceImpl";
    }
}

那么运行以上测试,会报错:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.faj.UserServiceTest': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.faj.inject.UserService' available: expected single matching bean but found 2: doctorUserServiceImpl,teacherUserServiceImpl

这时候,就要和@Qualifier一起使用:
UserService依旧有两个实现类:DoctorUserServiceImpl和TeacherUserServiceImpl:

@Service(value = "doctorUserService") // 给bean加上name
public class DoctorUserServiceImpl implements UserService {
    public String getName() {
        return "DoctorUserServiceImpl";
    }
}

// TeacherUserServiceImpl代码同上,省略

@SpringBootTest
public class UserServiceTest {
    @Autowired
    @Qualifier(value = "doctorUserService") // 使用该注解避免type带来的歧义
    private UserService userService;

    @Test
    public void test() {
        System.out.println(abc.getName()); // 打印结果:DoctorUserServiceImpl
    }
}

最后,@Autowired按name匹配:

@Service(value = "abc")
public class DoctorUserServiceImpl implements UserService {
    public String getName() {
        return "DoctorUserServiceImpl";
    }
}

@Service // bean默认是类名(首字母小写)
public class TeacherUserServiceImpl implements UserService {
    public String getName() {
        return "TeacherUserServiceImpl";
    }
}

@SpringBootTest
public class UserServiceTest {
    @Autowired
    private UserService abc; // 此时是按name匹配

    @Autowired
    private UserService teacherUserServiceImpl; // 此时是按name匹配

    @Test
    public void test() {
        System.out.println(abc.getName()); // 打印结果:DoctorUserServiceImpl
        System.out.println(teacherUserServiceImpl.getName()); // 打印结果:TeacherUserServiceImpl
    }
}

@Inject

@Inject属于JSR-330定义的Java的依赖注入标准(https://www.jcp.org/en/jsr/detail?id=330),使用@Inject的时候需要先加上依赖:

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

@Inject的用法和@Autowired基本相似:

不同点在于:@Autowired有个参数是required(默认为true),即在没有找到bean的时候,报NoSuchBeanDefinitionException;但如果required=false的时候,则不报错,会set null。举个例子:

@SpringBootTest
public class UserServiceTest {
    @Autowired(required = false)
    @Qualifier(value = "abc") // 并不存在name = abc的bean
    private UserService userService;

    @Test
    public void test() {
        System.out.println(userService); //此时的userService=null
    }
}

@Inject则没有这个功能,如果找不到适配的bean,则会报错:

@SpringBootTest
public class UserServiceTest {
    @Inject
    @Named(value = "abc")
    private UserService userService;

    @Test
    public void test() {
        System.out.println(userService); // 报错
    }
}

此时报错:org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.faj.inject.UserService' available: expected at least 1 bean which qualifies as autowire candidate.

@Resource

@Resource是JSR-250的规范,在实现依赖注入的时候,先按name进行匹配,其次是type,最后是@Qualifier。

Spring通过CommonAnnotationBeanPostProcesser来处理该注解。和@Inject不同的是,@Resource不需要额外引入jar包。

上一篇 下一篇

猜你喜欢

热点阅读