自定义复杂bean注册到spring

来源:互联网 发布:矩阵行列式的计算 编辑:程序博客网 时间:2024/06/05 09:02

自定义复杂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)

@Configurationpublic 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接口

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

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

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

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

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