Spring 注解驱动(一)基本使用规则
Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)
一、基本使用
@Configuration
@ComponentScan(basePackages = "com.github.binarylei",
excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class})}
)
@Lazy(false)
public class AnnnotationConfig {
// Scope 可取四个值:SCOPE_SINGLETON、SCOPE_PROTOTYPE、SCOPE_SESSION、SCOPE_REQUEST
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public User user() {
return new User();
}
}
启动测试:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnnotationConfig.class);
// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// context.register(AnnnotationConfig.class);
// context.refresh();
User user = context.getBean(User.class);
}
二、@ComponentScan
@Configuration
@ComponentScan(basePackages = "com.github.binarylei",
excludeFilters = {
@Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {User.class}),
@Filter(type = FilterType.CUSTOM,classes = MyFilter.class)
}, useDefaultFilters = false
)
public class AnnnotationConfig {
}
自定义的包扫描如下:
public class MyFilter implements TypeFilter {
/**
* @param metadataReader 当前类的信息
* @param metadataReaderFactory 获取其他类的信息
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// 1. 当前类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 2. 当前类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 3. 当前类的资源信息(类路径)
Resource resource = metadataReader.getResource();
return true;
}
}
三、@Conditional
@Bean
@Conditional(MyCondition.class)
public User user() {
return new User();
}
// 条件装配
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 1. IOC 容器
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 2. 类加载器
ClassLoader classLoader = context.getClassLoader();
// 3. 环境变量
Environment environment = context.getEnvironment();
// 4. 可以向容器中注册 BeanDefinition
BeanDefinitionRegistry registry = context.getRegistry();
return environment.getProperty("os.name").contains("Windows");
}
}
四、@Import
给容器中注册组件有以下方式:
- @Bean
- 包扫描(@ComponentScan) + 注解(@Componet/@Repository/@Service/@Controller)
- @Import
- @Import({User.class}) 导入单个组件
- @Import({User.class, MyImportSelector.class}) MyImportSelector 批量导入组件
- @Import({User.class, MyImportBeanDefinitionRegistrar.class}) MyImportBeanDefinitionRegistrar 批量导入组件
- FactoryBean
@Import({User.class, MyImportSelector.class})
@Import({User.class, MyImportBeanDefinitionRegistrar.class})
public class AnnnotationConfig {
}
// 返回类名的全定限名称
public class MyImportSelector implements ImportSelector {
/**
* @param importingClassMetadata 获取标注 @Import 注解的类所有注解信息(不仅仅是 @Import)
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 不要返回 null,否则会报空指针异常
return new String[]{User.class.getName()};
}
}
// 使用 BeanDefinitionRegistry 注册
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* @param importingClassMetadata 获取标注 @Import 注解的类所有注解信息(不仅仅是 @Import)
* @param registry 向容器中注册 BeanDefinition
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
boolean definition1 = registry.containsBeanDefinition("red");
boolean definition2 = registry.containsBeanDefinition("blue");
if (definition1 && definition2) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(User.class);
registry.registerBeanDefinition("user", beanDefinition);
}
}
}
五、Bean 的生命周期
- @Bean(initMethod = "init", destroyMethod = "destroy")
- 实现 InitializingBean, DisposableBean 接口
每天用心记录一点点。内容也许不重要,但习惯很重要!