# my-spring
**Repository Path**: panleiming/my-spring
## Basic Information
- **Project Name**: my-spring
- **Description**: No description available
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-06-26
- **Last Updated**: 2021-08-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring
# 目录
1. spring5注解
1. 配置组件
2. spring的扩展点
1. 扫描自定义的类或注解
2. 使用Conditional注解自定义加载类
3. 实现ImportSelector接口自定义加载类
4. 实现ImportBeanDefinitionRegistrar接口自定义加载类
5. 通过FactoryBean实现Bean的注册封装
# spring5注解
## 配置组件
| 注解名称 | 说明 |
| -------------- | ------------------------------------------------------------ |
| @Configuration | 把一个类作为一个IOC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。 |
| @ComponentScan | 在配置类上加上@ComponentScan注解。该注解默认会扫描该类所在的包下所有的配置类,相当于之前的\ |
| @Scope | 用于指定scope作用域的(用在类上)singleton-单例 prototype-原型,多例 request-主要应用于web模块,同一次请求只创建一个实例 session-主要应用于web模块,同一个session只创建一个对象 |
| @Lazy | 表示延迟初始化 只针对单例Bean起作用,默认启动容器时不创建Bean,调用时才进行创建 |
| @Conditional | Spring4开始提供,它的作用是按照一定的条件进行判断,满足条件给容器注册Bean。 |
| @Import | 导入外部资源 |
| @PostConstruct | 用于指定初始化方法(用在方法上) |
| @PreDestroy | 用于指定销毁方法(用在方法上) |
| @DependsOn | 定义Bean初始化及销毁时的顺序 |
# spring的扩展点
## 扫描自定义的类或注解
### 实现原理
实现`org.springframework.core.type.filter.TypeFilter`,然后在@Component进行filter的设置
### 例子
**实现自动加载所有以Custom结尾的类**
编写自己的Filter类
```java
public class MyFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// 获取当前的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
return classMetadata.getClassName().endsWith("Custom");
}
}
```
对@ComponentScan注解进行引用
```java
@Configuration
@ComponentScan(basePackages = "com.plm.learning", useDefaultFilters = false,
includeFilters = {@ComponentScan.Filter(value = MyFilter.class, type = FilterType.CUSTOM)})
public class ComponentScanConfig {
}
```
编写测试类进行测试
```java
public class SpringMain {
public static void main(String[] args) {
ApplicationContext act = new AnnotationConfigApplicationContext(ComponentScanConfig.class);
System.out.println("测试ComponentScan注解");
String[] names = act.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
}
```
## 使用Conditional注解自定义加载类
### 实现原理
实现`org.springframework.context.annotation.Condition`,然后通过@Conditional进行配置条件
### 例子
**实现根据操作系统,加载指定的类,即如果是Window操作系统,加载WindowClass类,如果是Linux操作系统,加载LinuxClass类**
编写自己的Condition类
```java
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String osName = environment.getProperty("os.name");
System.out.println(osName);
if (osName.contains("Linux")) return true;
return false;
}
}
public class WindowCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String osName = environment.getProperty("os.name");
System.out.println(osName);
if (osName.contains("Window")) return true;
return false;
}
}
```
对Bean进行条件判断
```java
@Configuration
public class ConditionalConfig {
@Conditional(value = {LinuxCondition.class})
@Bean
public OsClass linux() {
return new LinuxClass();
}
@Conditional(value = {WindowCondition.class})
@Bean
public OsClass window() {
return new WindowClass();
}
}
```
编写测试类测试
```java
public static void main(String[] args) {
ApplicationContext act = new AnnotationConfigApplicationContext(ConditionalConfig.class);
System.out.println("------------------测试Conditional注解");
OsClass osClass = act.getBean(OsClass.class);
System.out.println(osClass.toString());
}
```
## 实现ImportSelector接口自定义加载类
### 实现原理
通过实现`org.springframework.context.annotation.ImportSelector`接口,并通过@Import注解实现自定义Bean的加载
### 例子
**需要引入config包下的ConditionalConfig配置类,加载对应的bean**
编写自己的ImportSelector类实现
```java
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{AImportBean.class.getName(), BImportBean.class.getName(), ConditionalConfig.class.getName()};
}
}
```
使用@Import注解引入自定义类
```java
@Configuration
@Import(value = {MyImportSelector.class})
public class ImportConfig {
}
```
编写测试类测试
```java
public class SpringMain {
public static void main(String[] args) {
ApplicationContext act = new AnnotationConfigApplicationContext(ImportConfig.class);
String[] names = act.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
}
```
## 实现ImportBeanDefinitionRegistrar接口自定义加载类
### 实现原理
通过实现`org.springframework.context.annotation.ImportBeanDefinitionRegistrar`接口,并通过@Import注解实现自定义Bean的加载
### 例子
**只有IOC中存在了Father和Mother,才将Child注册到IOC容器中**
编写自己的注册类并实现ImportBeanDefinitionRegistrar接口
```java
public class MyImportBeanDefinitionRegistry implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// BeanDefinitionRegistry bean注册信息
boolean fatherFlag = registry.containsBeanDefinition(Father.class.getName());
boolean motherFlag = registry.containsBeanDefinition(Mother.class.getName());
if (fatherFlag && motherFlag) {
BeanDefinition child = new RootBeanDefinition(Child.class);
registry.registerBeanDefinition("child", child);
}
}
}
```
添加@Import注解
```java
@Configuration
@Import(value = { Father.class, Mother.class, MyImportBeanDefinitionRegistry.class})
public class ImportConfig {
}
```
编写测试类测试
```java
public class SpringMain {
public static void main(String[] args) {
ApplicationContext act = new AnnotationConfigApplicationContext(ImportConfig.class);
String[] names = act.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
}
```
## 通过FactoryBean实现Bean的注册封装
### 实现原理
通过实现**org.springframework.beans.factory.FactoryBean**接口,封装对Bean的注册
### 例子
**通过FactoryBean封装Monkey类**
创建自己的FactoryBean实现类
```java
public class MonkeyFactoryBean implements FactoryBean {
@Override
public Monkey getObject() throws Exception {
return new Monkey("Hello", "猴子");
}
@Override
public Class> getObjectType() {
return Monkey.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
```
使用@Bean注解声明
```java
@Configuration
public class BeanConfig {
@Bean
public MonkeyFactoryBean monkey() {
return new MonkeyFactoryBean();
}
}
```
编写测试类进行测试
```java
public class SpringMain {
public static void main(String[] args) {
ApplicationContext act = new AnnotationConfigApplicationContext(BeanConfig.class);
System.out.println("------------------测试FactoryBean");
Monkey monkey = act.getBean("monkey", Monkey.class);
System.out.println(monkey);
MonkeyFactoryBean factoryBean = act.getBean("&monkey", MonkeyFactoryBean.class);
System.out.println(factoryBean);
}
}
```