文章目录
@Component
- 第一种方式是@Component方式,标志这个类是一个Bean对象
- 要放在启动类的目录或者子目录下,不然需要在加上@ComponentScan来扫描
- 通过加在类上实现
@Component
class Test{
}
- 还有同等注解@Controller加在控制层,@Service服务层,@Repository持久层,@Configuration配置类,因为他们都使用了@Component
@Bean
- 第二种@Bean,这个注解要加在方法上,然后返回值是要实例化的类
//必须先让这个类被springboot扫描到@Bean才会起作用
@Configuration
class Test{
@Autowired
TestClass testClass;
//返回了实例那么这个实例会被springboot所管理
@Bean
public TestClass getTestClass(){
return new TestClass();
}
@PostConstruct
public void print(){
System.out.println(testClass);
}
}
class TestClass{
}
@Import
- 第三种@Import注解,可以直接导入想要被springboot管理的类
@Configuration
//value是一个数组,可以写多个class。比如a.class,b.class
@Import(TestClass.class)
class Test{
@Autowired
TestClass testClass;
@PostConstruct
public void print(){
System.out.println(testClass);
}
}
class TestClass{
}
@Import搭配ImportSelector
- 第四种@Import搭配ImportSelector,实现ImportSelector的方法实例化多个bean
@Configuration
@Import(TestClass.class)
class Test{
@Autowired
TestSelectImports testSelectImports;
@PostConstruct
public void print(){
System.out.println(testSelectImports);
}
}
//TestClass类似于一个实例化类的工具类,自身不会被springboot所管理
class TestClass implements ImportSelector {
//返回值是一个字符串数组,也是需要类的全类名
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{TestSelectImports.class.getName()};
}
}
class TestSelectImports{
}
- 输出:
@Import搭配ImportBeanDefinitionRegistrar
- 第五种是@Import搭配ImportBeanDefinitionRegistrar,实现这个接口的方法会交给我们一个BeanDefinitionRegistry,实现这个接口的都是工厂类,所以就是我们可以直接通过这个接口的方法把bean直接注册到工厂中
@Configuration
@Import(TestClass.class)
class Test{
@Autowired
TestSelectImports testSelectImports;
@PostConstruct
public void print(){
System.out.println(testSelectImports);
}
}
class TestClass implements ImportBeanDefinitionRegistrar {
//AnnotationMetadata是谁导入了这个类也就是Test类
//BeanDefinitionRegistry可以简单理解成Bean工厂,然后可以直接注册Bean
//每个Bean都会被转换成BeanDefinition,里边包含了Bean的所有元数据信息
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("testSelectImports",new RootBeanDefinition(TestSelectImports.class));
}
}
class TestSelectImports{
}
- 输出:
BeanFactoryPostProcessor
- 第六种我们可以实现BeanFactoryPostProcessor接口,他会返回给我们一个BeanFactory,我们可以任意操作,这是spring的一个扩展点,可以让我们在实例化Bean之前对元数据信息进行任意修改
@Component
class TestBeanFactory implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//这个接口只有两个实现类,一个XmlFactory现实了DefaultListableBeanFactory并且被标记为废弃了
//所以把它转换成子类,功能更多
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
//直接向工厂注册Bean
defaultListableBeanFactory.registerBeanDefinition("testSelectImports",new RootBeanDefinition(TestSelectImports.class));
}
}
class TestSelectImports{
}
BeanDefinitionRegistryPostProcessor
- 第七种是实现BeanDefinitionRegistryPostProcessor,它实现了上边的BeanFactoryPostProcessor,所以也有这个接口的功能
@Component
class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor{
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
beanDefinitionRegistry.registerBeanDefinition("test",new RootBeanDefinition(TestBeanDefinitionRegistry.class));
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
//跟上边一样就不演示了
}
}
class TestBeanDefinitionRegistry{
public TestBeanDefinitionRegistry(){
System.out.println("实例化TestBeanDefinitionRegistry");
}
}
- 输入:
FactoryBean
- 第八种是实现FactoryBean接口,这是一个工厂,也是一个Bean,可以用来生产对象,但也会被IOC所管理
@Component
//可以指定泛型
class MyFactoryBean implements FactoryBean<Object>{
@Override
public Object getObject() throws Exception {
//返回的就是要交给IOC管理的Bean
return new Object();
}
@Override
public Class<?> getObjectType() {
//Class对象
return Object.class;
}
}
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Demo123Application.class, args);
//获取对象,通过名字获取的是返回的对象
//通过&名字获取的是FactoryBean的对象
System.out.println(run.getBean("myFactoryBean"));
System.out.println(run.getBean("&myFactoryBean"));
}
}
- 输出:
总结
- 这些方式中有的只能帮我们创建Bean对象,但有的会返回给我们一个Bean工厂或者其他,我们拿到以后可以进行很多操作,不止是创建Bean,比如给了我们一个BeanFactory,我们都拿到了BeanFactory那么是不是很多功能都可以实现,所以可以做很多自己想做的事情