SpringBoot原理篇-Bean的8种加载方式

1.XML方式声明bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
  <context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
  <!--声明自定义bean-->
  <bean id="testService" class="com.Learning1.service.impl.Service" scope="singleton"/>
  <!--声明第三方开发bean-->
  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/>
</beans>

2.XML+注解方式声明bean

  • 此种方式需要在xml配置文件中声明命名空间
    开启命名空间后,指定包扫描位置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context.xsd">
  <context:component-scan base-package="com.Learning2"/>
</beans>

然后使用@Component注解以及其衍生注解@Controller,@Service,@Repository定义bean

@Service
public class AccountServiceImpl implements AccountService {
}

如果要定义第三方bean,需要使用@Bean注解定义在方法上面,并将所在类定义为配置类或Bean

@Configuration
//@Component
public class DbConfig {
  
  @Bean
  public DruidDataSource getDataSource(){
    DruidDataSource dataSource = new DruidDataSource();
    return dataSource;
  }

}

@Configuration注解包含了@Component注解

3.纯注解加载Bean

将xml配置文件改为一个配置类,用配置类取代xml配置的功能

@Configuration
@ComponentScan("com.Learning2")
public class SpringConfig {
}

关于FactoryBean接口的类

实现FactoryBean接口的类也是用来创建bean的,它存在的意义就在于能够在bean创建之前进行一系列的前置工作,比如判断创建条件,设置bean的信息等
对实现了FactoryBean接口的类加上@Bean注解,创建出来的bean不是那个类而是工厂造出来的对象的bean

public class TestDaoFactoryBean implements FactoryBean<TestDao> {

  @Override
  public TestDao getObject() throws Exception {
    return new TestDaoImpl();
  }

  @Override
  public Class<?> getObjectType() {
    return TestDao.class;
  }

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

关于@Configuration注解中的proxyBeanMethods属性

proxyBeanMethods=true可以保证调用有@Configuration注解的类的方法得到的对象是从spring容器中获取的而不是重新创建的。proxyBeanMethods的默认值是true

4.使用@Import注解导入

将需要其对象注册为Bean的类作为参数填入@Import注解中即可
这种形式可以有效的降低源代码与spring技术的耦合度

@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}

5.使用上下文对象在容器初始化完毕后注入bean

public class App {

  public static void main(String[] args) {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    applicationContext.register(UserService.class);
    applicationContext.registerBean("testDao",TestDao.class);
  }
}

6.通过ImportSelector接口加载bean

在配置类中导入实现了ImportSelector接口的类,实现对导入源的编程式处理
谁引用了这个类,这个类就可以获取这个类的一系列信息

@Import({MyImportSelector.class})
@EnableTransactionManagement
public class SpringConfig {
}
public class MyImportSelector implements ImportSelector {

  @Override
  public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    importingClassMetadata.hasAnnotation("org.springframework.context.annotation.Configuration");
    return new String[]{"com.Learning2.Dog"};
  }
}

7.通过ImportBeanDefinitionRegistrar接口创建bean

这种方法深入到bean的定义过程,使用方法和上一种类似
导入实现了ImportBeanDefinitionRegistrar接口的类,通过beanDefinition的注册器注册实名bean,实现对容器中bean的裁定

@Import({MyImportBeanDefinitionRegistrar.class})
public class SpringConfig {
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
      BeanDefinitionRegistry registry) {
    BeanDefinition beanDefinition = BeanDefinitionBuilder
                                    .rootBeanDefinition(Dog.class)
                                    .getBeanDefinition();
    registry.registerBeanDefinition("dodo",beanDefinition);
  }
}

8.BeanDefinitionRegistryPostProcessor决定bean的创建

这个接口是bean创建的最终决定接口,实现了这个接口的类可以处理之前过程中已经创建的bean,也可以新增bean,是一个最终裁定的接口
使用方式和上一个接口的方式类似
导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的最终裁定

@Import({MyPostProcessor.class})
public class SpringConfig {
}
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {

  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry)
      throws BeansException {
    BeanDefinition beanDefinition = BeanDefinitionBuilder
        .rootBeanDefinition(Dog.class)
        .getBeanDefinition();
    beanDefinitionRegistry.registerBeanDefinition("dodo",beanDefinition);
  }

  @Override
  public void postProcessBeanFactory(
      ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

  }
}

除了上面8种方式spring还有一些其他的加载bean的方式,这里就不再叙述了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值