1. 程式人生 > >2、Spring註解開發,第二天

2、Spring註解開發,第二天

一、TypeFilter指定過濾規則

最常用的兩個
FilterType.Annotation	按照註解
FilterType.ASSIGNABLE_TYPE  按照給定的型別
自定義規則
FilterType.Custom  自定義規則--實現TypeFilter介面[TypeFilter和FilterType有區別的]

1、FilterType.ASSIGNABLE_TYPE

package com.lee.config;

import com.lee.bean.Person;
import com.lee.service.BookService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

//@ComponentScan("com.lee")//自動掃描 value指定要掃描的包
@Configuration//告訴Spring這是一個配置類
//@ComponentScan(value="com.lee",excludeFilters = {
//        @ComponentScan.Filter(type=FilterType.ANNOTATION,value = Controller.class)
//})
@ComponentScan(value = "com.lee",useDefaultFilters=false,includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class),
        @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,value= BookService.class)
})
//FilterType.ANNOTATION 按照註解
//FilterType.ASSIGNABLE_TYPE 按照給定的型別
//FilterType.CUSTOM 按照自定義
public class MainConfig {

    //Bean 給容器註冊一個bean,型別為返回值的型別,id預設使用方法名作為id
    //@Bean("名字")可以給bean修改名稱
    @Bean
    public Person person(){
        return new Person(2,"lee2","male2");
    }


}

結果

mainConfig
bookController
bookService
person

2、FilterType.Custom

#metadataReader the metadata reader for the target class
#metadataReaderFactory  a factory for obtaining metadata readers for other classes (such as superclasses and interfaces)

MyTypeFilter.class

package com.lee.config;


import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class MyTypeFilter implements TypeFilter {


    /**
     *
     * @param metadataReader 讀取到當前正在掃描類的資訊
     * @param metadataReaderFactory  一個工廠,可以獲取到任何類的資訊
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        System.out.println("======>"+classMetadata.getClassName());
        if(classMetadata.getClassName().contains("ao")){
            System.out.println("---->"+classMetadata.getClassName());
            return true;
        }

        return false;
    }
}

MainConfig.class

package com.lee.config;

import com.lee.bean.Person;
import com.lee.service.BookService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

//@ComponentScan("com.lee")//自動掃描 value指定要掃描的包
@Configuration//告訴Spring這是一個配置類
//@ComponentScan(value="com.lee",excludeFilters = {
//        @ComponentScan.Filter(type=FilterType.ANNOTATION,value = Controller.class)
//})
@ComponentScan(value = "com.lee",useDefaultFilters=false,includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class),
        @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,value= BookService.class),
        @ComponentScan.Filter(type=FilterType.CUSTOM,value = MyTypeFilter.class)
})
//FilterType.ANNOTATION 按照註解
//FilterType.ASSIGNABLE_TYPE 按照給定的型別
//FilterType.CUSTOM 按照自定義
public class MainConfig {

    //Bean 給容器註冊一個bean,型別為返回值的型別,id預設使用方法名作為id
    //@Bean("名字")可以給bean修改名稱
    @Bean
    public Person person(){
        return new Person(2,"lee2","male2");
    }


}

結果:

mainConfig
bookController
bookDao
bookService
person

二、Scope設定元件作用域

spring預設Bean都是單例項的

1、單例-SINGLETON

MainConfig2.class

package com.lee.config;

import com.lee.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan(value = "com.lee")//包掃描
@Configuration//這是個配置類
public class MainConfig2 {

    @Bean
    public Person person(){
        return new Person(1,"張三","male");
    }
}

MainTest.class

package com.lee;

import com.lee.bean.Person;
import com.lee.config.MainConfig;
import com.lee.config.MainConfig2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainTest {


    @Test
    public void test01(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
        Person person1 = (Person) context.getBean("person");
        Person person2 = (Person) context.getBean("person");
        System.out.println("person1 == person2 : "+(person1==person2));
    }

}

結果:

person1 == person2 : true

2、原型-PROTOTYPE

MainConfig2.class

package com.lee.config;

import com.lee.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@ComponentScan(value = "com.lee")//包掃描
@Configuration//這是個配置類
public class MainConfig2 {

    @Scope(value = "prototype")
    @Bean
    public Person person(){
        return new Person(1,"張三","male");
    }
}

結果:

person1 == person2 : false

三、懶載入

單例項bean:預設在容器啟動的時候建立物件

懶載入:容器啟動不建立物件,等第一次呼叫的時候才建立物件

1、預設

MainConfig2.class

package com.lee.config;

import com.lee.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@ComponentScan(value = "com.lee")//包掃描
@Configuration//這是個配置類
public class MainConfig2 {

    @Scope(value = "prototype")
    @Bean
    public Person person(){
        return new Person(1,"張三","male");
    }
}

2、懶載入 lazy

MainConfig2.class

package com.lee.config;

import com.lee.bean.Person;
import org.springframework.context.annotation.*;

@ComponentScan(value = "com.lee")//包掃描
@Configuration//這是個配置類
public class MainConfig2 {

    @Lazy//懶載入
    @Scope(value = "prototype")
    @Bean
    public Person person(){
        return new Person(1,"張三","male");
    }
}

三、Conditional按條件註冊bean

按照一定的條件進行判斷,滿足條件給容器中註冊bean

WindowsCondition.class

package com.lee.conditions;


import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {


    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Window")){
            return true;
        }
        return false;
    }
}

LinuxCondition.class

package com.lee.conditions;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("linux")){
            return true;
        }
        return false;
    }
}

MainConfig2.class

package com.lee.config;

import com.lee.bean.Person;
import com.lee.conditions.LinuxCondition;
import com.lee.conditions.WindowsCondition;
import org.springframework.context.annotation.*;

@ComponentScan(value = "com.lee")//包掃描
@Configuration//這是個配置類
public class MainConfig2 {

//    @Lazy//懶載入
//    @Scope(value = "prototype")
    @Bean
    public Person person(){
        return new Person(1,"張三","male");
    }


    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01(){
        return new Person(2,"bill Gates","male");
    }

    @Conditional(LinuxCondition.class)
    @Bean("linus")
    public Person person02(){
        return new Person(3,"linus","male");
    }
}

MainTest.class

public class MainTest {

    @Test
    public void test02(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig2.class);
        ConfigurableEnvironment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        System.out.println("===>"+property);
        String[] beanNamesForType = context.getBeanNamesForType(Person.class);
        for(String bean : beanNamesForType){
            System.out.println(bean);
        }
    }
}

結果:

===>Windows 10
person
bill

在Run/Debug Configurations中加入環境變數

-Dos.name=linux

結果:

===>Linux
pe