专栏首页Java后端技术栈cwnaitSpringBoot如何使用注解装配Bean

SpringBoot如何使用注解装配Bean

在日常开发中,项目中大量的Bean的装配。今天就来聊聊如何使用注解装配Bean。这里与其说是SpringBoot装配Bean还是不如说是Spring注解来装配Bean。

装配Bean的方式主要有以下两种方式:

  1. 通过Java配置文件@Bean的方式来定义Bean
  2. 通过注解扫描的方式@Component@ComponentScan

一、使用@Bean的方式

首先写一个非常普通的实体类MyBean

public class MyBean {
    public String getName() {
        return "使用@Bean方式";
    }
}

然后定义一个MyBeanConfig类,在类上添加注解@Configuration

@Configuration该注解代表是一个 Java 配置文件 , Spring会根据它来生成 IoC 容器去装配 Bean。

@Bean 代表将 configBean方法返回的 POJO 装配到 IoC 容器中, name为Bean 的名称,如果没有配置它,则会将方法名称作为 Bean 的名称保存到 Spring IoC 容器中 。这里方法名称myBean就是MyBean保存在Spring IoC 容器中饿名称,如果在使用名称注入的时候就得使用myBean。否则会报错。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBeanConfig {
    @Bean
    public MyBean configBean() {
        return new MyBean();
    }
}

看看@Bean源码会发现,其实除了上面说的方法名称作为Bean在Spring IOC 容器中的Bean名称外,还可以使用@Beam("configBean")的方式。

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
    @AliasFor("name")
    String[] value() default {};

    @AliasFor("value")
    String[] name() default {};
    //...省略
}

下面我们创建一个测试controller。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class MyController {
    @Resource(name = "configBean")
    private MyBean configBean;

    @GetMapping("/test/bean")
    public String test(){
        return configBean.getName();
    }
}

启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

启动项目

测试工具使用IDEA的工具类里

访问:http://localhost:8080/test/bean

成功搞定。

用上面说的另外一种方式定义Beande 名称

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBeanConfig {
    @Bean("helloBean")
    public MyBean configBean() {
        return new MyBean();
    }
}

其他不动,再次启动启动类,就会报异常

所以得注入时候使用Bean名称也得跟着改(按照类型注入得另说,这里是演示Bean在Spring IOC中的名称)。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class MyController {
    //这里把bean在Spring IOC中的名称修改成上面定义的helloBean名称
    @Resource(name = "helloBean")
    private MyBean helloBean;

    @GetMapping("/test/bean")
    public String test(){
        return helloBean.getName();
    }
}

正常启动

访问也正常

ok,使用@Bean的方式就这样轻松搞定。

二、使用@Component方式

创建一个类MyComponentBean

import org.springframework.stereotype.Component;

@Component
public class MyComponentBean {

    public String getName(){
        return "使用@Component注解方式";
    }
}

一样的,写一个controller类来测试,MyComponentController

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class MyComponentController {

    @Resource
    private MyComponentBean myComponentBean;

    @GetMapping("/test/component")
    public String test(){
        return myComponentBean.getName();
    }
}

启动启动类main方法(和上面一样)。然后访问返回

成功。注解@Component 表明这个类将被Spring IoC容器扫描装配,bean的名称为componentBean。如果不配置这个值 ,那IoC 容器就会把类名第一个字母作为小写,其他的不变作为 Bean 名称放入到 IoC 容器中。

在工作中,controller里我们通常会注入各种service类。比如:UserInfoService、OrderService等。这些service上基本上都会使用@Service,在service层又会注入各种Repository、Mapper、Dao等,然后这些类上基本都添加了注解@Repository来装配Bean。

进入org.springframework.stereotype目录下会发现

其实@Controllert、@Service、@Repository注解上都添加了注解@Component

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

也就是说,除了@Component注解以外,还可以使用上面这三个注解装配Bean。

  • @Controller 控制器(注入服务)
  • @Service 服务(注入dao)
  • @Repository dao(实现dao访问)
  • @Component (把普通pojo实例化到spring容器中,相当于配置文件中的 )

OK,使用@Component的方式就这样轻松搞定。

三、使用@ComponentScan方式

@ComponentScan是Spring的包扫描组件,作用在配置类上。使用方式为:

@ComponentScan(value="com.example.demo")

其常用属性介绍:

value:代表需要扫描的包,扫描包下的有注解@Controller、@Service、@Repository、@Component注解标注的类,将其注入IOC容器。

excludeFilters :是一个 Filter[]数组,作用是排除不需要扫描的包或者类。Filter[]数组里面需要@Filter指定过滤规则,@Filter的type属性表示过滤的规则;@Filter的classes属性是个数组,里面包含需要过滤的类。

includeFilters :是一个 Filter[]数组,作用是指定扫描的时候只需要包含哪些组件。用法与excludeFilters相同

useDefaultFilters:默认过滤规则选项,false时,可以自定义过滤规则

使用场景很多,比如说上文提到的启动类中的SpringBootApplication注解中就使用到了。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
//使用@ComponentScan
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class}), 
@Filter(type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class})}
)
public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}

ok,今天就分析到这里。

本文分享自微信公众号 - Java后端技术全栈(jjs-2018),作者:田老师

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 精解四大集合框架:Set核心知识总结

    Set继承于Collection接口,是一个不允许出现重复元素,并且无序的集合,主要有HashSet和TreeSet两大实现类,另外LinkedHashSet也...

    Java后端技术全栈
  • 分布式锁的三种实现

    在单体时代使用ReentrantLock、synchronized等来实锁,以便保证资源的安全性。但是在分布式时代,则需要分布式锁才能实现资源的安全性。

    Java后端技术全栈
  • 设计模式 | 必备的责任链设计模式

    使多个对象都有机会处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

    Java后端技术全栈
  • 我们爬取了Billboard数据,发现了乐坛“造星法则”

    什么样的歌手在音乐制作公司眼中最受市场欢迎,且最能给公司带来收益?什么因素会影响这些艺术家们的表演?数据侠Weijie Deng这次自己当了一回音乐经纪人,用数...

    DT数据侠
  • 设计模式(三) | 为别人做嫁衣---代理模式

    谭庆波
  • vim命令用法 原

    补充: 空格键:向右移动一个字符 数字‘0’和shift+6:将光标移动到行首 shift+4:将光标移动到行尾

    阿dai学长
  • Lady Gaga和麦当娜谁才是gay圈女神?emoji数据啥都知道

    即时聊天工具如此普及的今天,各种emoji表情被网友们玩坏了。一个小小的表情包,却可以传递某种难以言说的情感,成了一种世界共通的语言。在全球最大音乐流媒体播放平...

    DT数据侠
  • 深度学习|卷积神经网络(CNN)介绍(前篇)

    01 — 回顾 以上推送了神经网络相关的介绍性内容和相关的基础理论,包括: 神经网络的基本结构:输入层,隐含层,输出层; 批随机梯度下降算法(mini-batc...

    double
  • PHP结合jquery ajax实现上传多张图片,并限制图片大小操作示例

    本文实例讲述了PHP结合jquery ajax实现上传多张图片,并限制图片大小操作。分享给大家供大家参考,具体如下:

    砸漏

扫码关注云+社区

领取腾讯云代金券