下面逐个介绍他们的用法:
这种方式使我们最为常见的一种,通过两类注解配合使用。
@ComponentScan注解用来标在配置类的上方,表示了需要对哪些包进行扫描。也可以通过excludeFilters属性来指明那些类型是不被扫描的组件。
第二类注解是指@Controller/@Service/@Repository/@Component四个中的一个,这些注解一般标在自己写的类的上方,表示他们是需要注册到spring容器中的。
有时候我们需要将一些类,不属于我们编写的类注册进spring容器当中,这时候我们不能再通过上面那种方式,而是需要在注解类中的方法上面加上@Bean注解,这样就会将该方法所返回的对象注册进spring容器当中。
spring中注册时实例默认是单实例的,即singleton。在ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿。
当我们在@Bean注解相同位置再添加一个@Scope(“prototype”)注解时,它表示Bean是多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象。
当然,我们也可以通过@Lazy注解加在@Bean注解相同位置来表示懒加载,这样即使是默认情况下的单例,容器启动的时候创建对象,也会变成容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化。
@Import注解使用时直接标注在配置类的上方,表示向Spring容器中注册哪些Bean。其中的value属性可以传入三种类型的值,分别是:直接类对象、ImportSelector和ImportBeanDefinitionRegistrar。
直接传入类对象就表示注册这些Bean;
传入ImportSelector的实现类,需要实现其中的selectImports()方法,返回的字符串数组表示要注册进容器中的Bean。例如:
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//方法不要返回null值
return new String[]{"com.gaishiHero.bean.Blue","com.gaishiHero.bean.Yellow"};
}
传入ImportBeanDefinitionRegistrar接口的实现类,需要实现其中的registerBeanDefinitions()方法,该方法第二个参数为BeanDefinitionRegistry,可以在该实现的方法中调用BeanDefinitionRegistry的registerBeanDefinition()方法,传入名称和BeanDefinition,就会将它们放入private final Map
中,就算注册完成。
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean definition = registry.containsBeanDefinition("com.gaishiHero.bean.Yellow");
boolean definition2 = registry.containsBeanDefinition("com.gaishiHero.bean.Blue");
if(definition && definition2){
//定义一个BeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
//注册一个Bean,指定bean名
registry.registerBeanDefinition("rainBow", beanDefinition);
}
}
外形与@Bean注解类似,也是通过在配置类中写方法。不过不同点在于方法的返回值是FactoryBean的实例,此时,注册进容器中的Bean不是这个FactoryBean的实例,而是其中实现的方法getObject()的返回值。
补充说明:FactoryBean接口有三个方法需要被实现:getObject()、getObjectType()和isSingleton()。getObject()返回真实注册进IOC容器中的Bean,getObjectType()返回FactoryBean创造对象的类型,isSingleton()返回是否是单例方式,如果是单例方式,只会调用getObject()方法一次,如果不是单例,则会多次调用getObject()方法。
当然,如果我们真的需要注册进容器中的Bean就是FactoryBean的实例,则需要在获取Bean的时候给id前面加一个&,例如&colorFactoryBean
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
//bean1是getObject()方法的返回值,bean2是colorFactoryBean对象本身
Object bean1 = applicationContext.getBean("colorFactoryBean");
Object bean2 = applicationContext.getBean("&colorFactoryBean");