-
以下无全部实现,只实现了核心部分
-
需要实现的效果
- 跟springcloud的
@FeignClient
注解一样不需要传统的实现类就能跟正常的bean一样使用 @Autowired
能注入使用-
分解各个步骤
- 自定义注解,定义所需的参数
- 使用spring的扫包获取interface上的特定注解类
- 为每个interface使用BeanDefinition注册到IOC容器
-
验证和代码实现BeanDefinition注册到IOC容器
这里我只是将各个点给串在一起,实现特定的业务需要,只是提供一种思想和部分逻辑的验证,其余逻辑相信大家都能实现.
- 相关代码
public class User {
private Long id;
private String name;
}
@Import(AnnotationBeanDefinitionDemo.Config.class)
public class AnnotationBeanDefinitionDemo {
@Autowired
public static void main(String[] args) {
//创建BeanFactory 容器
AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext();
//注册 Configuration(配置类)
applicationContext.register(AnnotationBeanDefinitionDemo.class);
//启动 spring 应用上下文
applicationContext.refresh();
//按类型查找查找依赖
//命名bean的注册方式
registerBeanDefinitionRegistry(applicationContext,"test",User.class);
//非命名bean的注册方式
registerBeanDefinitionRegistry(applicationContext,User.class);
System.out.println("config 类型的所有beans" + applicationContext.getBeansOfType(Config.class));
System.out.println("user 类型的所有beans" + applicationContext.getBeansOfType(User.class));
//显示的关闭 Spring 上下文
applicationContext.close();
}
/**
* 命名bean的注册方式
* @param registry
* @param beanName
* @param beanClass
*/
public static void registerBeanDefinitionRegistry(BeanDefinitionRegistry registry,String beanName,Class<?> beanClass){
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass);
beanDefinitionBuilder.addPropertyValue("id",10L)
.addPropertyValue("name","tt.victor");
if (StringUtils.hasText(beanName)){
//命名bean的注册方式
registry.registerBeanDefinition(beanName,beanDefinitionBuilder.getBeanDefinition());
}else {
//非命名bean的注册方式
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(),registry);
}
}
public static void registerBeanDefinitionRegistry(BeanDefinitionRegistry registry,Class<?> beanClass){
registerBeanDefinitionRegistry(registry,null,beanClass);
}
//2,通过 @Component 方式定义
@Component
public static class Config{
//1,通过 @Bean 方式定义
@Bean(name = {"user","st-user"})
public User user(){
User user= new User();
user.setName("st");
user.setId(11L);
return user;
}
}
}
核心代码
运行代码,得到结果
config 类型的所有beans{org.victor.spring.bean.definition.AnnotationBeanDefinitionDemo$Config=org.victor.spring.bean.definition.AnnotationBeanDefinitionDemo$Config@13c27452}
user 类型的所有beans{user=User{id=11, name='st', city=null, workCity=null, lifeCities=null}, test=User{id=10, name='tt.victor', city=null, workCity=null, lifeCities=null}, org.victor.spring.ioc.dependency.domain.User#0=User{id=10, name='tt.victor', city=null, workCity=null, lifeCities=null}}
一共有3个bean
user=User{id=11, name='st', city=null, workCity=null, lifeCities=null}
test=User{id=10, name='tt.victor', city=null, workCity=null, lifeCities=null}
org.victor.spring.ioc.dependency.domain.User#0=User{id=10, name='tt.victor', city=null, workCity=null, lifeCities=null}
- 其中user是靠注解生成的,其他两个是BeanDefinition注册生成的,现在要完成猜想的所有逻辑都已经有了,剩下的就是组装和验证了.
- 可能有同学要问,接口中定义的方法怎样在BeanDefinition生成的bean中体现呢?这个我认为可以参考
@FeignClient
中每个方法其实就是一个远程调用,我们可以根据自己的业务,再定义一个注解将每个方法上参数和注解内的参数通过代理来实现.