第二天:Spring annotation开发
目录:1、TypeFilter指定过滤规则 2、Scope设置组件作用域 3、懒加载Lazy 4、Conditional按条件注册bean
一、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
person
linus
@Conditional不仅可以标注在方法method上,也可以标注在类class上,这个类中所有bean注册才能被生效