目录
- 前言
- @ComponentScan+@Component
- @Configuration+@Bean
- 通过@Import注解
- 1.直接导入类的class
- 2.导入配置类
- 3.导入ImportSelector的实现类
- 4.导入ImportBeanDefinitionRegistrar的实现类
- 借助FactoryBean接口
- 借助BeanDefinitionRegistryPostProcessor接口
前言
我们在项目开发中都用到Spring,知道对象是交由Spring去管理。那么将一个对象加入到Spring容器中,有几种方法呢,我们来总结一下。
@ComponentScan+@Component
@ComponentScan可以放在启动类上,指定要扫描的包路径;该包路径下被@Component修饰的类,都会被注入到Spring容器中。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.gs.beanRegister")
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
com.gs.beanRegister包下:
import org.springframework.stereotype.Component;
@Component
public class A {
public void say() {
System.out.println("这是a");
}
}
注:在SpringBoot中,由于其自动装配的特性,所以@ComponentScan可以不加,只要@Component修饰的类和启动类在同一包下或者在启动类所在包的子包下。
@Configuration+@Bean
@Configuration用来声明一个配置类,如果它的方法被@Bean修饰,那么该方法返回的对象也会被注入到Spring容器中。
代码方面,BootStrap 类不动,A类的@Component去掉,com.gs.beanRegister包下建个配置类:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
@Configuration
public class MyConfiguration {
@Bean
public A a() {
return new A();
}
}
通过@Import注解
这个注解可能平时大家接触得不多,它有好几种使用方式。
1.直接导入类的class
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@Import(A.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
//B bean = context.getBean(B.class);
bean.say();
}
}
A类不用添加任何注解:
public class A {
public void say() {
System.out.println("这是a");
}
}
2.导入配置类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyConfiguration.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 使用@Import导入配置类时,@Configuration可以不加
//@Configuration
public class MyConfiguration {
@Bean
public A a() {
return new A();
}
}
3.导入ImportSelector的实现类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyImportSelector.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 返回要注入的bean的全路径,A类不用任何注解修饰
// SpringBoot的自动装配,就用到了这种方式:
// 返回配置类的全路径,配置类的@Bean方法返回的对象也能注入到容器中
return new String[] { A.class.getName() };
}
}
4.导入ImportBeanDefinitionRegistrar的实现类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyImportBeanDefinitionRegistrar.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportBeanDefinitionRegistrar implements
ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
// 构建bean的元数据,A类不用任何注解修饰
// spring-mybatis扫描mapper接口,生成代理类,就是用的这种方式
BeanDefinition definition = new RootBeanDefinition(A.class);
registry.registerBeanDefinition("a", definition);
}
}
借助FactoryBean接口
实现FactoryBean接口的类,除了本身会被注入外,getObject方法返回的对象也会被注入到Spring容器中。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyFactoryBean.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new A();
}
@Override
public Class<?> getObjectType() {
return A.class;
}
}
借助BeanDefinitionRegistryPostProcessor接口
在Spring容器启动时,会调用该接口的postProcessBeanDefinitionRegistry方法,大概意思是等BeanDefinition(上面提到的bean的元数据)加载完成后,再对它进行后置处理。所以可以在此调整BeanDefinition,从而把对应的bean注入。
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
BeanDefinitionRegistryPostProcessor postProcessor =
new MyBeanDefinitionRegistryPostProcessor();
context.addBeanFactoryPostProcessor(postProcessor);
context.refresh();
A a = context.getBean(A.class);
a.say();
}
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
public class MyBeanDefinitionRegistryPostProcessor implements
BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry
registry) throws BeansException {
BeanDefinition definition = new RootBeanDefinition(A.class);
registry.registerBeanDefinition("a", definition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory
beanFactory) throws BeansException {
}
}