Spring中@Bean注解的作用以及如何使用

@Bean

在spring中,将组件注入ioc容器的方式通常分为两种

  1. 第一种也就是我们常用的@Component@Controller@ServicResponse以及@Respository注解。
  2. 使用@Bean注解来注入组件。
    两种方式的区别:
  • @Component注解作用于类上,而@Bean注解作用于配置类中的某一个方法上;
  • @Component表明告知Spring为当前的这个类创建一个bean,而@Bean表明告知Spring此方法将会返回一个对象,将返回的对象注入到容器中。
  • @Bean注解的使用更加灵活。

如何使用?

在没有了解@Bean注解之前,相信大家都是以这种方式创建对象的:

    
    @AllArgsConstructor
    @NoArgsConstructor
    @Component
    public class User {
        private String name;
        private Integer age;
    }

然后直接通过@Autowired从容器中取出该对象

	@Autowired
	private User user

同样的场景,来使用@Bean试试。

    @Configuration
    public class MyConfiguration {
        @Bean
        public User user() {
            return new User();
        }
    }

该注解必须要在标有@Configuration的配置类中使用才会有效。
上述代码表示,将@Bean注解修饰的方法的返回值注入到IOC容器中。

	@Autowired
	private User user

通过上述几段代码,你可能很难发现@Bean注解灵活在哪里,反而还要作用在配置类中,更麻烦!

使用场景

场景1: 有时候我们需要根据条件来注入组件。

    @Configuration
    public class MyConfiguration {
        @Bean
        public User user() {
        	int i = 10;
        	if(i < 7) {
        		return new User("jack", 20);
      		} else {
      			return new User("david", 18);
      		}
        }
    }

场景2: 想象一下如果我们需要使用外部引入的lib中的组件时怎么办?使用@Component注解标注到别人的源码上面?显然这是不现实的,这个时候@Bean就可以发挥其优势了。

	@Configuration
    public class MyConfiguration {
        @Bean
        public ArrayList<User> list() {
            ArrayList<User> list = new ArrayList<>();
            list.add(new User("nacy", 17));
            return list;
        }
    }

使用@Bean注解在实际项目中解决的问题

在微服务的两个模块,其中模块A作为公共模块,模块B(SpringBoot模块)导入了模块A的Maven依赖(dependency),在项目运行时只启动模块B,模块A相当于一个静态的公共模块,不会去使用SpringBoot启动它。

模块A:

  • 配置类:
    @Configuration
    @EnableWebSecurity  // 开启Security
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    	@Autowired
    	private EmployeeRolePath employeeRolePath;
    	
        @Override
        protected void configure(HttpSecurity http) throws Exception {
     		List<String> uri = employeeRolePath.getUri();
        }
    
  • EmployeeRolePath:
    	@Component
    	@ConfigurationProperties("role.employee.path")
    	public class EmployeeRolePath {
    	
    	    private List<String> uri;
    	
    	    public List<String> getUri() {
    	        return uri;
    	    }
    	
    	    public void setUri(List<String> uri) {
    	        this.uri = uri;
    	    }
    	}
    

模块B:

  • 配置类,继承了模块A的配置类
    	@Configuration
    	@EnableWebSecurity  // 开启Security
    	public class SecurityConfig extends WebSecurityConfig {
    			// ........
    			// .........
    	}
    
  • yml配置文件:
    role:
      admin:  # 需要admin权限的访问路径
          path:
            uri:
              - /admin/adminRole/**
      employee: # 需要employee权限的访问路径
          path:
            uri:
              - /admin/category/**
              - /admin/dish/**
              - /admin/flavor/**
              - /admin/setmeal/**
    

先说一下我要实现的功能:要使上述yaml配置文件中的配置成功绑定到EmployeeRolePath类中并生效。

很显然,上述代码肯定不会生效,原因就是我们启动模块B时,Spring只能够扫描到本模块中的配置类SecurityConfig,以及它继承模块A中的配置类WebSecurityConfig,而作用在EmployeeRolePath类上的注解是不可能为生效的,原因就是模块A根本没启动,没有人去扫描他,它只是一个静态的模块而已。

解决:

在模块A的配置类中使用@Bean注解注入EmployeeRolePath组件。

	@Configuration
	@EnableWebSecurity  // 开启Security
	public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	    @Override
	    protected void configure(HttpSecurity http) throws Exception {
	 		List<String> uri = employeeRolePath().getUri();
	    }
	    
	    @Bean
	    public EmployeeRolePath employeeRolePath() {
	        return new EmployeeRolePath();
	}

如上述在本配置类中要使用该组件,直接调用employeeRolePath()就能获取到容器中的EmployeeRolePath组件了。

为什么这样可以生效?
上述说了,当模块B启动时,会先初始化加载模块B的配置类,而模块B的配置类又继承了模块A的配置类,所以Spring是能够扫描到模块A中的配置的,并且它们是在同一个IOC容器中的,所以在模块B中定义的配置文件也会生效。

  • 14
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值