Spring中@Autowired 注解的注入规则

默认根据类型,匹配不到则根据bean名字

测试:

1.声明一个dao接口

public interface BaseDao {
    void add();
}

2.两个实现dao接口的实现类,并配置上@Repository注解,且不指定该注解的属性,默认在Ioc容器中的Bean名为类名首字母小写的字符串

@Repository
public class OracleRepository implements BaseDao {
    @Override
    public void add() {
        System.out.println("oracle repository");
    }
}
@Repository
public class MySqlRepository implements BaseDao {
    @Override
    public void add() {
        System.out.println("mysql repository");
    }
}

3.现在增加一个Service层的接口

public interface HelloService {
    void add();
}

4.为Service接口增加实现类

@Service
public class HelloServiceImpl implements HelloService {
    @Autowired
//    @Qualifier(value = "mySqlRepository")
    private BaseDao baseDao;
    @Override
    public void add() {
        System.out.println("hello service impl");
        baseDao.add();
    }
}
扫描二维码关注公众号,回复: 5847949 查看本文章

5.测试程序

public class AppTest {
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // @Component, @Controller, @Service, @Repository如果不指定属性那么bean的名字默认都是类名首字母小写
        // 所以 HelloServiceImpl 类的bean名字为  helloServiceImpl
        HelloService helloService = (HelloService) context.getBean("helloServiceImpl");
        helloService.add();
    }
}

结果报错

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloServiceImpl': 
Unsatisfied dependency expressed through field 'baseDao'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'com.convict.dao.BaseDao' available: expected single matching bean but found 2: mySqlRepository,oracleRepository
Exception in thread
"main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloServiceImpl': Unsatisfied dependency expressed through field 'baseDao'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.convict.dao.BaseDao' available: expected single matching bean but found 2: mySqlRepository,oracleRepository

分析:

因为第2步中,声明了两个dao的实现类,但是@Repository 注解中没有指定这个Bean的名字,所以Spring默认给他们起了类名首字母小写为它们各自的名字,即

OracleRepository实例化后在IoC容器中的bean名字为 oracleRepository

MySqlRepository实例化后在Ioc容器中的bean名字为 mySqlRepository

而在 HelloServiceImpl 类中使用了@Autowired 注解修饰   private BaseDao baseDao; @Autowired注解会先去根据类型找,即找到这个接口的实例化对象,即子类,然后装配给这个属性,然而这个接口现在有两个实现类,所以此时@Autowired 注解无法识别找哪个,即报上面的异常

现在把第4步的注释取消,即显示的用 @Qualifier 注解指定了IoC容器的一个bean来装配,下面我指定用 mySqlRepository

@Service
public class HelloServiceImpl implements HelloService {
    @Autowired
    @Qualifier(value = "mySqlRepository")
    private BaseDao baseDao;
    @Override
    public void add() {
        System.out.println("hello service impl");
        baseDao.add();
    }
}

结果:

装配成功了

但是如果我不想用@Qualifier 注解呢,那么我们还有两种方法,第一种是在dao的实现类@Repository 注解中指定该bean的名字跟 注入的属性的名字一致即可

如修改OracleRepository 类

@Repository("baseDao")
public class OracleRepository implements BaseDao {
    @Override
    public void add() {
        System.out.println("oracle repository");
    }
}

可看到,我指定了这个 bean名字就叫做baseDao,而MySQLRepository 类中@Repository注解不指定属性,则它由Spring自己命名,为 mySQLRepository

现在Service文件是这个样子,属性名字就叫做 baseDao,跟上面我指定的bean名字是一样的

@Service
public class HelloServiceImpl implements HelloService {
    @Autowired
//    @Qualifier(value = "mySqlRepository")
    private BaseDao baseDao;
    @Override
    public void add() {
        System.out.println("hello service impl");
        baseDao.add();
    }
}

测试程序启动,结果如下

装配成功了,把IoC中名字为 baseDao的对象 注入了

现在说一下最后一种,我不指定@Repository 的任何一个属性,我现在新增加一个类,也是实现BaseDao 接口的

@Repository
public class SqlServerRepository implements BaseDao {
    @Override
    public void add() {
        System.out.println("SqlServer repository");
    }
}

现在Ioc中该bean的名字为 sqlServerRepository

现在修改Service文件,不叫baseDao了, 接口还是BaseDao,但名字叫做 sqlServerRepository,代码如下

@Service
public class HelloServiceImpl implements HelloService {
    @Autowired
//    @Qualifier(value = "mySqlRepository")
    private BaseDao sqlServerRepository;
    @Override
    public void add() {
        System.out.println("hello service impl");
        sqlServerRepository.add();
    }
}

结果如下:

总结:

要么不指定bean的名字,由spring自己生成,那么@Autowired 注解修饰的属性的名字,要跟spring生成的bean 的名字一致即可

要么指定一下bean的名字,且@Autowired 注解修饰的属性的名字,跟自己指定的bean的名字一致即可

要么不管@Repository,也不管属性怎么命名,那么需要在@Autowired 之后再加一个@Qualifier 注解,指明从IoC容器中拿哪个名字的bean

猜你喜欢

转载自www.cnblogs.com/convict/p/10688335.html
今日推荐