Spring 关于Bean的注册方式

注册方式

  1. 通过配置XML注册
  2. 通过@Bean注册
  3. 通过Beanfactory注入

需要注册的Bean

/**

* @Description: 自定义Bean

* @Author: Jonas

* @Date: 2020-06-01 22:52

*/

@Data

@Slf4j

publicclassMyBean{

private String name;

privateint age;

publicMyBean(String name, int age){

this.name = name;

this.age = age;

log.info("调用构造函数创建Bean,name={},age={}",name,age);

}

}

具体实现

1. 通过配置XML注册

applicationContext.xml

<beanid="myBean"class="com.jonas.config.bean.MyBean" >

<constructor-argname="name"value="Jonas"/>

<constructor-argname="age"value="18"/>

</bean>

通过xml注入是Spring MVC中注入Bean常用的方式

现在项目中越来越多Spring Boot项目,而且配置XML的方式还是相对麻烦且难以维护,下面介绍的两种方式是现阶段中相对常见的方式

2. 通过@Bean注册

建造者模式创建Bean,这个类后面都会有提到

**

* @Description: MyBeanBuilder 常见的建造者的方法

* @Author: Jonas

* @Date: 2020-06-0122:57

*/

publicclassMyBeanBuilder{

private String name;

privateint age;

public MyBeanBuilder withName(String name){

this.name = name;

returnthis;

}

public MyBeanBuilder withAge(int age){

this.age = age;

returnthis;

}

publicstatic MyBeanBuilder getInstance(){

returnnew MyBeanBuilder();

}

public MyBean build(){

returnnew MyBean(this.name,this.age);

}

}

通过@Bean创建Spring对象

/**

* @Description: 使用@Bean创建并注入Spring

* @Author: Jonas

* @Date: 2020-06-01 23:09

*/

@Configuration

@Slf4j

publicclassAnnotationBean{

// 通过@Bean 调用构造函数,生成Bean,并将Bean交由BeanFactory管理

@Bean

public MyBean myBean(){

MyBean myBean = new MyBean("hello", 10);

log.info("向spring中注入成功 myBean");

return myBean;

}

// 通过@Bean 调用建造方法,生成Bean,本质和上面的方式差不多

@Bean

public MyBean myBean2(){

MyBean tom = MyBeanBuilder.getInstance()

.withName("Tom")

.withAge(22)

.build();

log.info("向spring中注入成功 myBean2");

return tom;

}

}

其实两者本质都是调用构造函数创建,只是后者是间接将参数传递给了构造函数

2. 通过Beanfactory动态注入

/**

* @Description: 自定义Bean工厂

* @Author: Jonas

* @Date: 2020-06-01 22:50

*/

@Configuration

@Slf4j

publicclassMyBeanFactoryimplementsInitializingBean{

@Autowired

private ApplicationContext applicationContext; // Spring上下文

public MyBean createBean(String name,int age,String string){

log.info("调用工厂方法创建Bean");

log.info("输出第三个参数===>{}",string);

returnnew MyBean(name,age);

}

@Override

publicvoidafterPropertiesSet()throws Exception {

// 通过 DefaultListableBeanFactory 动态生成Bean

DefaultListableBeanFactory capableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();

log.info("==================进入方法====================");

// 动态创建10个类型为MyBean的不同的Bean对象

for (int i=0;i<10;i++) {

// 调用构造方法动态创建

// registerBean(applicationContext,"dynamic"+i,MyBean.class,"Bean"+i,10+i);

// 调用工厂方法动态创建Bean

registerBean(applicationContext,"dynamic"+i,

"myBeanFactory","createBean","Bean" + i,20+i, UUID.randomUUID().toString());

}

}

/**

* 调用Bean构造函数,注册Bean到上下文中

* @param applicationContext

* @param registerName

* @param clazz

* @param args

* @param <T>

* @return

*/

private <T> T registerBean(ApplicationContext applicationContext,

String registerName,

Class<T> clazz,

Object... args){

if(applicationContext.containsBean(registerName)) {

Object bean = applicationContext.getBean(registerName);

if (bean.getClass().isAssignableFrom(clazz)) {

return (T) bean;

} else {

thrownew RuntimeException("BeanName 重复 " + registerName);

}

}

BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);

for (Object arg : args) {

// 设置构造函数参数

beanDefinitionBuilder.addConstructorArgValue(arg);

}

BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();

BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory();

beanFactory.registerBeanDefinition(registerName, beanDefinition);

return applicationContext.getBean(registerName, clazz);

}

/**

* 调用工厂方法,注册Bean到上下文中

* @param applicationContext

* @param registerName

* @param factoryBeanClazz

* @param factoryMethod

* @param args

* @param <T>

* @return

*/

private <T> T registerBean(ApplicationContext applicationContext,String registerName,

String factoryBeanClazz,String factoryMethod,Object... args){

BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder

// 建造一个父类的Bean,不可为其他类的子类

//.rootBeanDefinition()

// 建造一个子类的Bean,必须传递一个父类Bean的名称,不可为其他类的父类

// .childBeanDefinition()

// 建造一个标准的Bean

.genericBeanDefinition()

// 设置工厂方法和工厂类

.setFactoryMethodOnBean(factoryMethod, factoryBeanClazz);

for (Object arg: args) {

// 设置工厂方法参数

beanDefinitionBuilder.addConstructorArgValue(arg);

}

DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();

AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();

beanFactory.registerBeanDefinition(registerName,beanDefinition);

return (T) applicationContext.getBean(registerName);

}

}

调用工厂方法createBean动态创建10个不一样的Bean

调用构造方法动态创建10个不一样的Bean

总结

这三种是Bean常用的注册方式,第一种一般在SpringMVC中较为常见,但是感觉不是很方便。第二种是Spring Boot中常用的Bean注册方式,一般在配置类中经常需要手动加载Bean到Spring中去。第三种常常用于需要创建一批同类型的有一定重复命名规则的Bean,像前段时间对Swagger进行动态分组的时候就通过这个方式创建

附录

动态创建Swagger分组

EnableModuleTag.java

/**

* @Description: 自动设置模块标记,便于日志模块的自动写入和swagger-ui的分组管理

* @author: Jonas

* @since: 2020/5/29 14:52

*/

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

public@interface EnableModuleTag {

String moduleName()default "SYSTEM";

}

SwaggerConfig.java

/**

* @Description: swagger-ui配置,单体应用自动创建Swagger-ui分组

* @author: Jonas

* @since: 2020/5/30 22:53

*/

@Configuration

@EnableSwagger2

@Slf4j

publicclassSwaggerConfigimplementsInitializingBean{

private Set<String> groupName = new HashSet<>();

@Autowired

private ApplicationContext applicationContext;

@Bean

public Docket docket(){

// basePackage 需要扫描注解生成文档的路径

returnnew Docket(DocumentationType.SWAGGER_2)

// 分组名用aaa开头以便排在最前面

.groupName("默认分组(全部)")

.apiInfo(apiInfo())

.select()

.apis(RequestHandlerSelectors.basePackage("com.jonas.data"))

.paths(PathSelectors.any())

.build();

}

//基本信息,页面展示

private ApiInfo apiInfo(){

returnnew ApiInfoBuilder()

.title("SwaggerAPI")

.description("xxxx项目接口api")

//版本号

.version("1.0.0")

.build();

}

private Docket buildDocket(String groupName){

returnnew Docket(DocumentationType.SWAGGER_2)

.apiInfo(apiInfo())

.groupName(groupName)

.select()

.apis(method -> {

// 每个方法会进入这里进行判断并归类到不同分组,

// **请不要调换下面两段代码的顺序,在方法上的注解有优先级**

// 该方法上标注了模块名称

if (method.isAnnotatedWith(EnableModuleTag.class)) {

EnableModuleTag annotation = method.getHandlerMethod().getMethodAnnotation(EnableModuleTag.class);

if (annotation.moduleName() != null && annotation.moduleName().length() != 0) {

if (Arrays.asList(annotation.moduleName()).contains(groupName)) {

returntrue;

}

}

}

// 方法所在的类是否标注了?

EnableModuleTag annotationOnClass = method.getHandlerMethod().getBeanType().getAnnotation(EnableModuleTag.class);

if (annotationOnClass != null) {

if (annotationOnClass.moduleName() != null && annotationOnClass.moduleName().length() != 0) {

if (Arrays.asList(annotationOnClass.moduleName()).contains(groupName)) {

returntrue;

}

}

}

returnfalse;

})

.paths(PathSelectors.any())

.build();

}

/**

* 动态得创建Docket bean

* @throws Exception

*/

@Override

publicvoidafterPropertiesSet()throws Exception {

// ApiConstantVersion 里面定义的每个变量会成为一个docket

Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(EnableModuleTag.class);

for (Iterator<Object> iterator = beanMap.values().iterator(); iterator.hasNext();) {

Object bean = iterator.next();

EnableModuleTag annotation = bean.getClass().getAnnotation(EnableModuleTag.class);

// 获取模块名称,并放置到set中

String moduleName = annotation.moduleName();

groupName.add(moduleName);

// 动态注入bean

AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();

// if (autowireCapableBeanFactory instanceof DefaultListableBeanFactory) {

DefaultListableBeanFactory capableBeanFactory = (DefaultListableBeanFactory) autowireCapableBeanFactory;

// 要注意 "工厂名和方法名",意思是用这个bean的指定方法创建docket

// 获取驼峰命名

String registerName = CommonUtils.getHumnName("swagger_config_"+moduleName);

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder

.genericBeanDefinition()

.setFactoryMethodOnBean("buildDocket", "swaggerConfig")

.addConstructorArgValue(moduleName)

.getBeanDefinition();

capableBeanFactory.registerBeanDefinition(registerName, beanDefinition);

log.info("注册Bean:{} 到Spring中",registerName);

// }

}

}

}

用法:

controller加上注解标注

启动的时候自动注册不同的Bean到Spring中,从而实现根据模块自动创建不同分组,方便管理API

以上是 Spring 关于Bean的注册方式 的全部内容, 来源链接: utcz.com/a/21298.html

回到顶部