1. 程式人生 > >Spring 註解驅動(一)基本使用規則

Spring 註解驅動(一)基本使用規則

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

給容器中註冊元件有以下方式:

  1. @Bean
  2. 包掃描(@ComponentScan) + 註解(@Componet/@Repository/@Service/@Controller)
  3. @Import
    • @Import({User.class}) 匯入單個元件
    • @Import({User.class, MyImportSelector.class}) MyImportSelector 批量匯入元件
    • @Import({User.class, MyImportBeanDefinitionRegistrar.class}) MyImportBeanDefinitionRegistrar 批量匯入元件
  4. 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 的生命週期

  1. @Bean(initMethod = "init", destroyMethod = "destroy")
  2. 實現 InitializingBean, DisposableBean 介面

每天用心記錄一點點。內容也許不重要,但習慣很重要!