目录
1. 基于XML配置文件
2. 基于XML+注解方式声明bean
·自定义bean
·第三方bean
3.注解方式声明配置类
扩展1,FactoryBean
扩展2,加载配置类并加载配置文件(系统迁移)
扩展3,proxyBeanMethods=true的使用
4. 使用@Import注解导入要注入的bean对应的字节码
扩展4,使用@Import注解导入配置类
5. 编程式方式
6. 实现了ImportSelector接口
7.实现ImportBeanDefinitionRegistrar接口
8.实现了BeanDefinitionRegistryPostProcessor接口
总结
便于练习,导一个比较大的包
org.springframework
spring-context
5.3.23
使用注解(如@Component、@Service、@Repository等)来标识Bean类
在配置类上写@Component才可以被扫描到 (@Configuration也行更推荐)
@Component
public class DbConfig {
@Bean
public DruidDataSource getDataSource(){
DruidDataSource ds = new DruidDataSource();
return ds;
}
}
@Configuration
//@Configuration配置项如果不用于被扫描可以省略
@ComponentScan("com.itheima")
public class SpringConfig {
@Bean
public DruidDataSource getDataSource(){
DruidDataSource ds = new DruidDataSource();
return ds;
}
}
初始化实现FactoryBean接口的类,实现对bean加载到容器之前的批处理操作
public class BookFactoryBean implements FactoryBean {
public Book getObject() throws Exception {
Book book = new Book();
// 进行book对象相关的初始化工作
return book;
}
public Class> getObjectType() {
return Book.class;
}
}
public class SpringConfig8 {
@Bean
public BookFactoryBean book(){
return new BookFactoryBean();
}
}
在新的注解开发的项目中使用原来的老的配置文件,使用@ImportResource,然后指定xml文件
@Configuration
@ComponentScan("com.itheima")
@ImportResource("applicationContext-config.xml")
public class SpringConfig2 {
}
使用proxyBeanMethods=true可以保障调用此方法得到的对象是从容器中获取的而不是重新创建的
默认是true
@Configuration(proxyBeanMethods = true)
public class SpringConfig3 {
@Bean
public Book book(){
System.out.println("book init ...");
return new Book();
}
}
先拿到了配置类的对象,从容器中获取,再调用了方法,得到的就是同一个对象
public class AppObject {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig3.class);
SpringConfig3 config = ctx.getBean("SpringConfig3", SpringConfig3.class);
SpringConfig3.book();
SpringConfig3.book();
}
}
@Import(Dog.class)
public class SpringConfig5 {
}
被导入的bean无需使用注解声明为bean
public class Dog {
}
此形式可以有效的降低源代码与Spring技术的耦合度,在spring技术底层及诸多框架的整合中大量使用
使用这种方式可以加载配置类,并且也不用加@Configuration了
@Import(DbConfig.class)
public class SpringConfig {}
·使用上下文对象在容器初始化完毕后注入bean
这种只能使用AnnotationConfigApplicationContext,其他不生效
public class AppImport {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(SpringConfig5.class);
ctx.register(Cat.class);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
导入实现了ImportSelector接口的类,实现对导入源的编程式处理,谁导入他,他就能查谁的户口,把他里面的注解方法等等全部可以获取到
在配置类上@Import(MyImportSelector.class)
public class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata metadata) {
boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Import");
if(flag){
return new String[]{"com.itheima.domain.Dog"};
}
return new String[]{"com.itheima.domain.Cat"};
}
}
导入实现了ImportBeanDefinitionRegistrar接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的裁定,例如对现有bean的覆盖,进而达成不修改源代码的情况下更换实现的效果
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(BookServiceImpl2.class)
.getBeanDefinition();
registry.registerBeanDefinition("bookService", beanDefinition);
}
}
导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的最终裁定
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(BookServiceImpl4.class)
.getBeanDefinition();
registry.registerBeanDefinition("bookService", beanDefinition);
}
}
总之,实现了BeanDefinitionRegistryPostProcessor接口可以对最终的Bean定义产生影响,可以动态地添加、修改或删除Bean定义,从而对应用程序的配置和行为进行定制化。