自定义复杂bean注册到spring

时间:2022-05-22 16:05:17

自定义复杂bean注册到spring

A依赖B, B依赖C,A和C是有spring创建,而B要自己去创建,并且像B的有很多,比如B的调用实际是一个RPC

在什么时机去装机B并能让spring找到这个依赖呢?spring的FactoryBean就可以解决(不是BeanFactory)

下面以 Retrofit 为例简单说明,类B的bean都是由retrofit创建(动态代理)

先声明一个 FactoryBean的实现

public class ServiceFactoryBean implements FactoryBean {


private Retrofit retrofit;

private Class serviceClass;

public void setServiceClass(Class serviceClass){
this.serviceClass = serviceClass;
}

public void setRetrofit(Retrofit retrofit) {
this.retrofit = retrofit;
}

@Override
public Object getObject() throws Exception {

return retrofit.create(this.serviceClass);
}

@Override
public Class getObjectType() {
return serviceClass;
}

@Override
public boolean isSingleton() {
return true;
}
}

在spring进行bean定义处理的时候就把类B的bean在spring中注册一下(实现接口BeanDefinitionRegistryPostProcessor)

@Configuration
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

@Autowired
BeanNameGenerator beanNameGenerator;

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
logger.info("Invoke Metho postProcessBeanDefinitionRegistry");

Reflections reflections = new Reflections("com.myapp.api.service");
Retrofit retrofit = retrofit();
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(RetrofitService.class);
for (Class<?> serviceClass : annotated) {
for(Annotation annotation : serviceClass.getAnnotations()){
if (annotation instanceof RetrofitService){//自定义注解RetrofitService,都需要通过retrofit创建bean
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(ServiceFactoryBean.class);
beanDefinition.setLazyInit(true);
beanDefinition.getPropertyValues().addPropertyValue("retrofit", retrofit);
beanDefinition.getPropertyValues().addPropertyValue("serviceClass", serviceClass);
String beanName = this.beanNameGenerator.generateBeanName(beanDefinition, registry);
registry.registerBeanDefinition(beanName, beanDefinition);
}
}
}
}

public Retrofit retrofit() {

final String basic = Base64.encodeToString(token.getBytes());

final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(60, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(60, TimeUnit.SECONDS);

okHttpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();

Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", basic)
.method(original.method(), original.body());

Request request = requestBuilder.build();
return chain.proceed(request);
}
});

return new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(JacksonConverterFactory.create())
.client(okHttpClient)
.build();
}

}

如自己定义的类B接口

@RetrofitService
public interface UserService {
@POST("/user/register")
Call<Object> register(@Body User user);
}

为什么要用BeanDefinitionRegistryPostProcessor,可以看看org.springframework.context.support.AbstractApplicationContext#refresh

BeanFactory 它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

FactoryBean 作用是产生其他bean实例getObjectType()

到此完成,需要用户的地方直接使用按照驼峰命名引用或使用注解Autowired