JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。

1.12. 基于java的容器配置

// 用户标记一个spring配置类,之前是根据xml启动spring上下文
// 相当于 xml文件  <beans></beans>
@Configuration
@ComponentScan(basePackages = "com.tuling")   //== <context:component-scan base-package="com.tuling" >
// 使用@PropertySource 引入外部属性资源文件
@PropertySource("classpath:db.properties")
/* @Import
  1 导入其他的配置类@Import(SecondJavaConfig.class)
  2.导入类注册为Bean @Import(Role.class)
  3.导入ImportSelector实现类,可以注册多个bean@Import(MyImportSelector.class)
  4.导入ImportBeanDefinitionRegistrar实现类,可以注册多个BeanDefinition
*/
@Import(MyImportBeanDefinitionRegistrar.class)
public class IocJavaConfig {
}
ApplicationContext ioc;
    @Before
    public void before(){
        //加载spring上下文
        ioc = new AnnotationConfigApplicationContext(IocJavaConfig.class);
    }
    @Test
    public void test01(){
        ioc.getBean("userController", UserController.class);
    }

@Bean是一个方法级别的注解,它与XML中的 元素类似。注解支持 提供的一些属性,例如 * init-method * destroy-method * autowiring * name

开发者可以在@Configuration类或@Component类中使用@Bean注解。

@Value("${mysql.username}")
    private String name;
    @Value("${mysql.password}}")
    private String password;
    @Value("${mysql.url}")
    private String url;
    @Value("${mysql.driverClassName}")
    private String driverClassName;

    /**
     *  可以将一个类的实例(可以干预Bean实例化过程),注册为一个Bean
     *  会自动将返回值作为Bean的类型    将方法名作为bean的名字
     *  @Bean(name = "dd") 设置bean的名字及别名(替换)
     *  <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
     *  @Bean(initMethod = "",destroyMethod = "") = <bean class="xx" id="xx" init-method="initByConfig" destroy-method="destroyByConfig"></bean>

     怎么去自动依赖外部Bean:直接在方法里面写上需要依赖的参数即可,不需要写@Autowired
    怎么去自动依赖内部Bean:直接调用方法即可
     */
    @Bean(name = {"dataSource","dd"})
    //@Scope("prototype")  //作用域
    public DruidDataSource dataSource(Role role){
        DruidDataSource dataSource=new DruidDataSource();
        dataSource.setName(name);
        dataSource.setPassword(password);
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        System.out.println(user3());

        return  dataSource;
    }
  • 我们可以使用方法参数来实现该依赖关系,如以下示例所示:
@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}
@Bean(initMethod = "initByConfig",destroyMethod = "destroyByConfig")
public User userconf(){

    return  new User();
}
@Configuration
public class MyConfiguration {

    @Bean
    @Scope("prototype")
    public Encryptor encryptor() {
        // ...
    }
}
//默认情况下,配置类使用@Bean方法的名称作为结果bean的名称。 
//但是,可以使用name属性覆盖此功能,如以下示例所示:
@Configuration
public class AppConfig {

    @Bean(name = "myThing")
    //多个别名:@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
    public Thing thing() {
        return new Thing();
    }
}
//当Bean彼此有依赖关系时,表示依赖关系就像调用另一个bean方法一样简单.如下例所示:
@Configuration
public class AppConfig {

    @Bean
    public BeanOne beanOne() {
        return new BeanOne(beanTwo());
    }

    @Bean
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}
//就像在Spring XML文件中使用<import/>元素来帮助模块化配置一样,
//@Import 注解允许从另一个配置类加载@Bean定义,如下例所示:
@Configuration
public class ConfigA {

    @Bean
    public A a() {
        return new A();
    }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {

    @Bean
    public B b() {
        return new B();
    }
}

Import注解的源码,导入四种类型

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

	/**
	 * {@link Configuration @Configuration}, {@link ImportSelector},
	 * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
	 */
	Class<?>[] value();

}
/* @Import
  1 导入其他的配置类@Import(SecondJavaConfig.class)
  2.导入类注册为Bean @Import(Role.class)
  3.导入ImportSelector实现类,可以注册多个bean@Import(MyImportSelector.class)
  4.导入ImportBeanDefinitionRegistrar实现类,可以注册多个BeanDefinition
*/
@Import(MyImportBeanDefinitionRegistrar.class)
public class IocJavaConfig {
}

导入ImportSelector实现类,可以注册多个bean(springboot)

新建两个bean,注意是没有通过@Component注解注册到ioc中的

public class Person {
    @Value("fztx")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}



public class Wife {
    @Value("迪丽热巴")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

1.新建MyImportSelector实现ImportSelector

@Component
public class MyImportSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 可以以字符串的形式注册多个Bean
        // 字符串必须是类的完整限定名  getBean不能根据名字获取获取的, 必须要根据类型获取
        return new String[]{"com.tuling.beans.Person",Wife.class.getName()};
    }
}

2.在主config中导入

@Import(MyImportSelector.class)
public class IocJavaConfig {
}

3.ioc容器获取

@Test
    public  void test05(){
        Person bean = ioc.getBean(Person.class);//必须通过类型获取
        System.out.println(bean.getName());
    }

导入ImportBeanDefinitionRegistrar实现类,可以注册多个BeanDefinition(bean定义)

(BeanDefinition是spring源码中很重要的一个类关于BeanDefinition的详细讲解

同样是上边的Person

1.新建MyImportBeanDefinitionRegistrar 实现ImportBeanDefinitionRegistrar 

@Component
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
       GenericBeanDefinition beanDefinition=new GenericBeanDefinition();
        beanDefinition.setBeanClass(Person.class);
        registry.registerBeanDefinition("person",beanDefinition);
    }

}

 2.在主config中导入

@Import(MyImportBeanDefinitionRegistrar.class)
public class IocJavaConfig {
}

3.ioc容器获取

@Test
    public  void test05(){
        Person bean = ioc.getBean(Person.class);
        System.out.println(bean.getName());
    }