1.因为BeanDefinition会在ioc容器加载的先注册, 而BeanFactoryPostProcess就是在所有的BeanDefinition注册完后做扩展的,所以要
先加载BeanFactoryPostProcess
2. 解析配置类的组件 它就实现BeanFactoryPostProcess, 所以要先去加载BeanFactoryPostProcess
Bean的创建顺序是由BeanDefinition的注册顺序来决定的, 当然依赖关系也会影响Bean创建顺序 (A-B)。
主要是由注解(配置)的解析顺序来决定:
这里有三种重要的方法给Spring 容器提供配置元数据。
基于Java的配置,允许你在少量的Java注解的帮助下,进行你的大部分Spring配置而非通过XML文件。
以@Configuration 注解为例,它用来标记类可以当做一个bean的定义,被Spring IOC容器使用。
另一个例子是@Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文。
@Configuration
public class StudentConfig{
@Bean
public StudentBean myStudent(){
return new StudentBean();
}
}
应用:
@Component是 @Controller、@Repository、@Service的元注解
@Controller、@Repository、@Service分别对应三层架构,@Controller标注在控制器上,@Repository标注在数据访问层,@Service标注在业务层
4种:
这个注解表明bean的属性必须在配置的时候设置,通过一个bean定义的显式的属性值或通过自动装配,若@Required
注解的bean属性未被设置,容器将抛出BeanInitializationException。
如何解决:将是否必须注入将默认的’是’改为‘否’
@Autowired(required = false)
private Role role;
多个类实现了LoginService接口,当运行
@Autowired
private LoginService loginService;
@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
@Autowired 注解提供了更细粒度的控制,不像by name,by type自动注入的方式(为所有提供了set()方法的属性自动注入),@Autowired 默认按照类型自动注入,如果类型匹配到多个再按照名字自动注入,不需要额外提供set()方法。
@Autowired可用于:构造函数、成员变量、Setter方法
@Autowired和@Resource之间的区别
@Autowired,Spring提供的,默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为
false)。
@Resource,JDK提供的,默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。
记住:@Autowired 通过Bean的后置处理器进行解析的
第一种:@Bean
第二种:ImportSelector的实现类,注册selectImports返回的数组(类全路径)则IOC容器批量注册,但是不能控制实例化过程
第三种:@Import类,但是不能控制实例化过程
第四种:@Import ImportBeanDefinitionRegistrar的实现类,手工注册beanDefinition
@Import(MyImportBeanDefinitionRegistrar.class)
MyImportBeanDefinitionRegistrar类,手工注册
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
RootBeanDefinition beanDefinition=new RootBeanDefinition(DruidDataSource.class);
beanDefinition.getPropertyValues().add("url","...");
beanDefinition.getPropertyValues().add("username","root");
registry.registerBeanDefinition("dataSource",beanDefinition);
}
}
第五种:实现BeanDefinitionRegistryPostProcessor,手工注册BeanDefinition
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
//手工注册
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition beanDefinition=new RootBeanDefinition(DruidDataSource.class);
beanDefinition.getPropertyValues().add("url","...");
beanDefinition.getPropertyValues().add("username","root");
registry.registerBeanDefinition("dataSource",beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
Spring在解析@ComponentScan的时候,拿到basePackage,如果没有设置,会将当前类所在的包的地址作为扫描包的地址