0%

Spring注入

文章字数:590,阅读全文大约需要2分钟

配置注解

  • @Configuration注解相当于将当前类当作一个bean注入的组件

  • @Bean将当前方法的返回值注入成为组件,beanid是方法名

  • @ComponentScan(value="com.xx.xx")扫描并注入的文件/文件包位置

  • AnnotationConfigApplicationContext(xxx.class)把指定的class当作配置文件加载一个上下文。

  • 指定扫描的包中标记有@Controller注解的类注入

    1
    2
    3
    @ComponentScan(value="com.xx.xx", includeFilters={
    @Filter(type=FilterType.ANNOTATION, classes={Controller.class})
    }, useDefaultFilter=false)

    使用excludeFilters即为排除
    useDefaultFilter即是否使用默认的扫描
    @Filter(type=FilterType.ASSIGNABLE_TYPE), classes={xx.class}指定注入的类

  • 自定义扫描器
    @Filter(type=FilterType.CUSTOM, classes={MyFilter .class}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MyFilter implements TypeFilter{
/** MetadataReader 当前扫描类信息 MetadataReaderFactory 其他任何类信息 */
@Override
public boolean match(MetadataReader r, MetadataReaderFactory f)thros IOException{
// 获取当前类注解信息
r.getAnnotationMetadata();
// 获取当前正在扫描的类信息
r.getClassMetadata();
// 类路径信息
r.getResource();
// 类信息
f.
return false;
}
}

单实例和多实例

  • 单实例在容器初始化时就创建(@Bean创建默认是单实例),可以使用@Lazy强制懒加载,第一次使用再创建。
  • 多实例用时创建(@Scope("prototype")注解)

注入判断

1
2
3
4
5
6
7
8
9
10
11
12
public class MyCondition implements Condition{
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){
// 获取当前IOC容器使用的beanFactory
context.getBeanFactory();
// 获取当前环境变量(例如当前的操作系统)
Enviroment enviroment = context.getEnviroment();
// 判断当前的操作系统
enviroment.getProperty("os.name");
return false;// 是否注入
}
}

注入时使用判断过滤器

1
2
3
4
5
@Coditional(MyCondition.class)
@Bean
public Object getOb(){
...
}

import注册Bean

注入的几种方式

  • @Bean一般用于导入第三方的组件
  • 包扫描+类上的标注注解
  • @Import能够快速给容器导入组件
  • Factorybean接口实现

import注册Bean的几种方式

1
2
3
// 注册类上直接注册,id是全类名
@Import(value={xx.class})
@Configuration
  • ImportSelector是一个接口,返回需要导入容器的全类名和数组
    1
    2
    3
    4
    5
    6
    public class MySelect implements ImportSelector{
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    // 返回类的全类名
    return new String[]{"com.xx.yy", "com.xx.zz"};
    }
    }
1
2
3
// 使用选择器注入
@Import(value={MySelect .class})
@Configuration
  • ImportBeanDefinitionRegistrar接口,满足条件注入Bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**AnnotationMetadata 当前类注解信息
* BeanDefinitionRegistry BeanDefinition注册类,把所需要添加到容器的bean加入
*/
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
boolean bean1 = registry.containsBeanDefintion("com.xx.yy");
boolean bean2 = registry.containsBeanDefintion("com.xx.zz");
// 如果这两个bean都存在于容器,那就创建Pig类到容器
if(bean1 && bean2) {
// 注册之前需要先对类封装一下(Spring中很多bean都这个类封装的)
RootBeanDefinition rootBeanDefinition = new BootBeanDefinition(Pig.class);
// 注册进容器
registry.registerBeanDefinition("pig", rootBeanDefinition );
}
}
1
2
3
// 使用ImportBeanDefinitionRegistrar注入
@Import(value={MyregisterBeanDefinitions.class})
@Configuration

FactoryBean接口注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public MyFactoryBean implements FactoryBean<MyClass>{
@Override
public MyClass getObject() throws Exception {
return new MyClass();
}
@Override
public Class<?> getObjectType() {
return MyClass.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
1
2
3
4
5
6
7
// 注入FactoryBean即为注入MyFactoryBean所包含的Class
// BeanFactory在获取bean时会判断,如果类型是FactoryBean,会调用其getObject方法,并返回内容。
// &getMyFactoryBean则是获取factory本身
@Bean
public MyFactoryBean getMyFactoryBean() {
return MyFactoryBean();
}

spring容器

  • beanDefinitionMap里面就是Spring的容器