spring基本組件及註解

clipboard.png

spring基本組件如上圖:spring

spring配置文件

最初使用xml配置文件,而後轉向註解。數組

//配置類====配置文件
@Configuration
public class MainConfig {
    //給容器中註冊一個bean, 類型爲返回值的類型, 
    //注意以@Bean註冊bean,Id默認爲方法名,也可經過@Bean註解的值來修改
    @Bean
    public Person person01(){
        return new Person("username",20);
    }
}



  public class MainTest2 { 
    public static void main(String args[]){
    //加載註解的配置文件         
        ApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class);    
        //從容器中獲取bean
        //Person person = (Person) app.getBean("person01");           
        //System.out.println(person);
        String[] namesForBean = app.getBeanNamesForType(Person.class);
        for(String name:namesForBean){
            System.out.println(name);
        }
    
    }
}

@ComponentScan掃描規則

@Configuration
@ComponentScan(value="com.enjoy.cap2", includeFilters={        
        @Filter(type=FilterType.ANNOTATION, classes={Controller.class})        
}, useDefaultFilters=false)   
public class Cap2MainConfig {
    //給容器中註冊一個bean, 類型爲返回值的類型, 
    @Bean
    public Person person01(){
        return new Person("james",20);
    }
}
  1. value的值說明是掃描此包下面的全部類
  2. includeFilters表示使用自定義的過濾器,此時useDefaultFilters應該爲false屏蔽默認過濾器,自定義的才生效(demo中表示只掃描Controller類型的類)
  3. 另外的excludeFilters就是在默認過濾器下再過濾指定的類,自定義過濾器便可,implements
    TypeFilter便可自定義

@ComponentScan value:指定要掃描的包
excludeFilters = Filter[] 指定掃描的時候按照什麼規則排除那些組件
includeFilters = Filter[] 指定掃描的時候只須要包含哪些組件
useDefaultFilters = false 默認是true,掃描全部組件,要改爲false
----掃描規則以下
FilterType.ANNOTATION:按照註解
FilterType.ASSIGNABLE_TYPE:按照給定的類型;好比按BookService類型
FilterType.ASPECTJ:使用ASPECTJ表達式
FilterType.REGEX:使用正則指定
FilterType.CUSTOM:使用自定義規則,自已寫類,實現TypeFilter接口session

//FilterType.CUSTOM的例子,經常使用
先新增自定義過濾規則類: TestTypeFilter
@ComponentScan(value="com.enjoy.cap2",includeFilters={app

@Filter(type=FilterType.CUSTOM,classes={TestTypeFilter.class})

},useDefaultFilters=false)ide

public class TestTypeFilter implements TypeFilter{
    private ClassMetadata classMetadata;

    /*
     * MetadataReader:讀取到當前正在掃描類的信息
     * MetadataReaderFactory:能夠獲取到其餘任何類信息
     */
    
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        //獲取當前類註解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //獲取當前正在掃描的類信息
        classMetadata = metadataReader.getClassMetadata();
        //獲取當前類資源(類的路徑)
        Resource resource = metadataReader.getResource();
        
        String className = classMetadata.getClassName();
        System.out.println("----->"+className);
        if(className.contains("er")){//當類包含er字符, 則匹配成功,返回true
            return true;
        }
        return false;
    }

}

@scope註解

spring中bean默認是單例singleton,@Scope(「prototype」)爲多實例。spa

//多實例
@Scope("prototype")
@Bean
public Person person(){
    return new Person("username",20);
}
  • prototype: 多實例:IOC容器啓動並不會去調用方法建立對象放在容器中,而是
    每次獲取的時候纔會調用方法建立對象
  • singleton: 單實例(默認):IOC容器啓動會調用方法建立對象放到IOC容器中
    之後每交獲取就是直接從容器(理解成從map.get對象)中拿
  • request: 主要針對WEB應用,同一次請求建立一個實例
  • session: 同一個session建立一個實例(主要掌握前面2個便可,後面2個瞭解)

lazy懶加載

@lazy當加入此註解時,則getBean調用的時候纔會把實例加載到IOC容器。操作系統


@Conditional條件註冊bean

public class WinCondition implements Condition{
    
    /*
    *ConditionContext: 判斷條件可使用的上下文(環境)
    *AnnotatedTypeMetadata: 註解的信息
    *
    */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // TODO 是否爲WINDOW系統
        //能獲取到IOC容器正在使用的beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //獲取當前環境變量(包括咱們操做系統是WIN仍是LINUX??)
        Environment environment = context.getEnvironment();
        String os_name = environment.getProperty("os.name");
        if(os_name.contains("Windows")){
            return true;
        }
        return false;
    }
}

//加入條件註解則會按自定義的邏輯註冊,true時註冊到容器
@Conditional(WinCondition.class)
@Bean("lison")
public Person lison(){
    System.out.println("給容器中添加lison.......");
    return new Person("Lison",28);
}

@Import註冊bean

@Import(value = { Dog.class,Cat.class,JamesImportSelector.class,JamesImportBeanDefinitionRegistrar.class })


public class JamesImportSelector implements ImportSelector{
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata){
        //返回全類名的bean
        return new String[]{"com.enjoy.cap6.bean.Fish","com.enjoy.cap6.bean.Tiger"};
    }
}

public class JamesImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /*
    *AnnotationMetadata:當前類的註解信息
    *BeanDefinitionRegistry:BeanDefinition註冊類
    *    把全部須要添加到容器中的bean加入;
    *    @Scope
    */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean bean1 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Dog");
        boolean bean2 = registry.containsBeanDefinition("com.enjoy.cap6.bean.Cat");
        //若是Dog和Cat同時存在於咱們IOC容器中,那麼建立Pig類, 加入到容器
        //對於咱們要註冊的bean, 給bean進行封裝,
        if(bean1 && bean2){
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Pig.class);
            registry.registerBeanDefinition("pig", beanDefinition);
        }
    }

}

給容器中註冊組件的方式:prototype

  • 1,@Bean: [導入第三方的類或包的組件],好比Person爲第三方的類, 須要在咱們的IOC容器中使用code

  • 2,包掃描+組件的標註註解(@ComponentScan: @Controller, @Service @Reponsitory @
    Componet),通常是針對 咱們本身寫的類,使用這個xml

  • 3,@Import:[快速給容器導入一個組件] 注意:@Bean有點簡單

    a,@Import(要導入到容器中的組件):容器會自動註冊這個組件,bean 的 id爲全類名
    b,ImportSelector:是一個接口,返回須要導入到容器的組件的全類名數組
    c,ImportBeanDefinitionRegistrar:能夠手動添加組件到IOC容器, 全部Bean的註冊可使用BeanDifinitionRegistry,寫JamesImportBeanDefinitionRegistrar實現ImportBeanDefinitionRegistrar接口便可

  • 4,使用Spring提供的FactoryBean(工廠bean)進行註冊,實現FactoryBean<T>接口便可,在實現方法getObject裏可寫註冊的實例。注意:如MyFactoryBean爲實現了FactoryBean<T>接口,getBean("myFactoryBean")獲取的實例爲實現的getObject方法裏的實例,getBean("&myFactoryBean")則爲MyFactoryBean實例,具體邏輯查看源碼可發現
相關文章
相關標籤/搜索