Solon

二、构建一个 Bean 的三种方式(IOC)

</> markdown

关于 Solon Bean 有两个重要的概念:名字,类型。对应的是:

  • 按名字注册,则按名字注入、按名字获取
  • 按类型注册,则按类型注入、按类型获取

1、手动(一般,在开发插件时用)

简单的构建:

//生成普通的Bean(只是注册,不会做别的处理;身上的注解会被乎略掉)
Solon.context().wrapAndPut(UserService.class, new UserServiceImpl());

//生成Bean,并触发身上的注解处理(比如类上有 @Controller 注解;则会执行 @Controller 对应的处理)
Solon.context().beanMake(UserServiceImpl.class);

更复杂的手动,以适应特殊的需求:

UserService bean = new UserServiceImpl();

//可以进行手动字段注入
Solon.context().beanInject(bean);

//可以再设置特殊的字段
bean.setXxx("xxx");


//包装Bean(指定名字的)
BeanWrap beanWrap = Solon.context().wrap("userService", bean); 
//包装Bean(指定类型的)
//BeanWrap beanWrap = Solon.context().wrap(UserService.class, bean);

//以名字注册
Solon.context().putWrap("userService", beanWrap); 
//以类型注册
Solon.context().putWrap(UserService.class, beanWrap); 

下面2种模式,必须要被扫描到。在不便扫描,或不须扫描时手动会带来一种自由感。

2、用配置器类

本质是 @Configuration + @Bean 的组合,并且 Config 要被扫描到

@Configuration
public class Config{
    //以类型进行注册(默认) //可用 @Inject(UserService.class) 注入
    @Bean 
    public UserService build(){
        return new UserServiceImpl();
    }
    
    //以名字进行注册 //可用 @Inject("userService") 注入
    @Bean("userService") 
    public UserService build2(){
        return new UserServiceImpl();
    }
    
    //同时以名字和类型进行注册 //支持类型或名字注入
    @Bean(name="userService", typed=true) 
    public UserService build3(){
        return new UserServiceImpl();
    }
}

使用带条件的构建

@Configuration
public class Config{
    //注解条件控制 (应对简单情况)
    @Bean
    @Condition(onProperty="${cache.enable} = true")
    public CacheService cacheInit(@Inject("${cache.config}") CacheServiceSupplier supper){
        return supper.get();
    }
    
    //手动条件控制 Bean 产生(应对复杂点的情况)
    @Bean
    public CacheService(@Inject("${cache.type}") int type){
        if (type == 1){
            return Solon.cfg().getBean("cache.config", MemCacheService.class);
        } else if (type == 2){
            return Solon.cfg().getBean("cache.config", RedisCacheService.class);
        } else if (type == 3){
            return Solon.cfg().getBean("cache.config", JdbcCacheService.class);
        } else{
            return new LocalCacheService();
        }
    }
}

顺带,还可以借用 @Configuration + @Bean 的组合,进行初始化

@Configuration
public class Config{
    @Bean
    public void titleInit(@Inject("${demo.title}") String title){
        Config.TITLE = title;
    }
    
    @Bean
    public void dsInit(@Inject("${demo.ds}") String ds) {
        String[] dsNames = ds.split(",");
        
        for (String dsName : dsNames) {
            Props props = Solon.cfg().getProp("demo.db-" + dsName);
            
            if (props.size() > 0) {
                //按需创建数据源
                DataSource db1 = props.getBean("", HikariDataSource.class);

                //手动推到容器内
                BeanWrap bw = Solon.context().wrap(DataSource.class, db1);
                Solon.context().putWrap(dsName, bw);
            }
        }
    }
}

3、使用组件注解(必须要能被扫描到)

a. 以类型进行注册(默认)

//@Singleton(false) //默认都是单例,如果非例单加上这个注解
@Component
public class UserServiceImpl implements UserService{

}

//通过 @Inject(UserService.class) 注入
//通过 Solon.context().getBean(UserService.class) 手动获取 //要确保组件已注册

b. 以名字进行注册

@Component("userService")
public class UserServiceImpl implements UserService{

}

//通过 @Inject("userService") 注入
//通过 Solon.context().getBean("userService") 手动获取 //要确保组件已注册

c. 以名字和类型同时进行注册

@Component(name="userService", typed=true)
public class UserServiceImpl implements UserService{

}

//通过 @Inject("userService") 注入
//通过 Solon.context().getBean("userService") 手动获取 //要确保组件已注册

//通过 @Inject(UserService.class) 注入
//通过 Solon.context().getBean(UserService.class) 手动获取 //要确保组件已注册

4、补充说明

使用以下接口时,记得给托管的 Bean 取好名字!

Map<String,UserService.class> userServiceMap = Solon.context().getBeansMapOfType(UserService.class)

//或者 

@Inject
Map<String,UserService.class> userServiceMap;