Spring Framework 5.0:注解的方式加载Bean之包扫描、@Autowired

前面我们已经了解到可以有2种方式来加载bean:
XML文件的方式和注解的方式。
http://blog.csdn.net/github_26672553/article/details/78793707

    public static void main(String[] args) throws Exception{

        // MyConfig类里的代码 好比是我们的xml文件
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);

        // 从配置文件中设置好了相关验证
        UserService userService = (UserService)context.getBean("myUserService"); // 这其实就是通过IoC容器的方式 初始化对象
        userService.userLogin("zhangSan","111111111");

    }

AnnotationConfigApplicationContext()其实可以传入多个(打上@Configuration注解的)类。
实际上项目中有很多个这样的配置类是很普遍的。

所以,上面我们硬编码的参数就不太合适了。

注解的方式加载Bean:包扫描

https://docs.spring.io/spring/docs/5.0.1.BUILD-SNAPSHOT/spring-framework-reference/core.html#beans-java-instantiating-container-scan

<beans>
        <context:component-scan base-package="com.acme"/>
</beans>

你也许见过上面这种XML定义的,针对某个package组件扫描。
现在我们并没有采用XML文件定义的方式,如何扫描包(package)?

    public static void main(String[] args) throws Exception{

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.scan("SpringLean"); // 扫描SpringLean这个包
        ctx.refresh();

        UserService userService = (UserService)ctx.getBean("myUserService");
        userService.userLogin("zhangSan","111111111"); // 打印:用户开始登录...
    }

Bean之间相互调用

1、我们创建一个NewsService类,代码如下:

package SpringLean;

public class NewsService {

    // 随便写一个方法吧
    public void showTitle(){
        System.out.println("这是新闻");
    }
}

2、当然为了能够通过注解的方式加载,所以要在MyConfig.java文件中(这个文件就相当于一个XML配置文件),也可以再创建一个这样的文件:

    @Bean
    public NewsService myNewsService(){
        return new NewsService();
    }

我们给myNewsService()方法打上了@Bean这个注解。

3、来到入口函数,测试一把

    public static void main(String[] args) throws Exception{

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.scan("SpringLean"); // 扫描SpringLean这个包
        ctx.refresh();

        NewsService newsService = ctx.getBean("myNewsService",NewsService.class);
        newsService.showTitle(); // 输出:这是新闻
    }

4、上面通过注解的方式加载Bean很好理解,但实际开发是复杂的,我们面临很多需求,比如:如果我们要在NewsService类里怎么调用UserService类呢?

public class NewsService {

    // 随便写一个方法吧
    public void showTitle(){
        System.out.println("这是新闻");

        new UserService(); // 错误
    }
}

难道直接在NewsService类中实例化UserService?肯定不行。
这样搞,对象之间的关联就不在同一个IoC容器里了。

@Autowired

@Autowired注解可以实现自动装配,以实现上面的需求。

package SpringLean;

import org.springframework.beans.factory.annotation.Autowired;

public class NewsService {

    @Autowired
    UserService userService; // 因为在配置类(MyConfig)里有个@bean注解的方法 返回UserService对象,所以这里是可以加载到的

    public void showTitle(){
        System.out.println("这是新闻");

        // 这样就可以在NewsService里 调用到UserService类定义的方法
        try {
            userService.userLogin("zhangSan","111111111");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

上面代码就完成了“在NewsService里调用UserService”。
那么实际有没有作用呢?我们需要测试

    public static void main(String[] args) throws Exception{

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.scan("SpringLean"); // 扫描SpringLean这个包
        ctx.refresh();

        NewsService newsService = ctx.getBean("myNewsService",NewsService.class);
        newsService.showTitle(); 
    }

我们在入口函数里只调用了NewsServiceshowTitle()方法(这个方法里会调用UserServiceuserLogin()方法),我们看执行后的控制台输出:

这是新闻
用户开始登录...

5、@Autowired不仅可以作用于属性上,还可以作用于方法上

package SpringLean;

import org.springframework.beans.factory.annotation.Autowired;

public class NewsService {

    UserService userService;

    @Autowired
    public void abc(UserService userService) {
        System.out.println("构造函数被自动执行");
        this.userService = userService;
    }


    public void showTitle(){
        System.out.println("这是新闻");

        // 这样就可以在NewsService里 调用到UserService类定义的方法
        try {
            userService.userLogin("zhangSan","111111111");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行输出:

构造函数被自动执行
这是新闻
用户开始登录...

@Qualifier

1、装配冲突

    @Bean
    public UserService myUserService(){
        UserService userService = new UserService();
        userService.setUserValidateConfig(this.userValidateConfig1());
        return userService;
    }

    @Bean
    public UserService myUS(){
        UserService userService = new UserService();
        userService.setUserValidateConfig(this.userValidateConfig1());
        return userService;
    }

如上面代码我们在MyConfig这个配置类中定义了2个返回UserService对象的方法,这样就会导致在UserService里使用@Autowired装配的时候发生“装配冲突”。
因为Autowired默认是以类型进行装配的,定义了2个同类型的,就不知道到底加载哪个了。

2、

    @Bean
    @Qualifier("us1")
    public UserService myUserService(){
        UserService userService = new UserService();
        userService.setUserValidateConfig(this.userValidateConfig1());
        return userService;
    }

    @Bean
    @Qualifier("us2")
    public UserService myUS(){
        UserService userService = new UserService();
        userService.setUserValidateConfig(this.userValidateConfig1());
        return userService;
    }

我们用不同的Qualifier来区分。

3、这样加载的时候,只需要

    UserService userService;

    @Autowired
    public void abc(@Qualifier("us1") UserService userService) {
        System.out.println("构造函数被自动执行");
        this.userService = userService;
    }

就不会发生冲突了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值