@Configuration
该注解作用在类上,告诉Spring这是一个配置类,与XML效果是一样的,我们接下来所使用的注解,需要在配置类中使用。
ApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
@Bean
将@Bean放在方法上使用,能够将Bean加入到IOC容器中,其返回值代表Bean的类型,其方法名代表Bean的id。
@Bean
public Pig pig() {
return new Pig();
}
@Scope扫描规则
在被标注为Bean的方法上可以使用@Scope,该注解的属性可以配置为
- singleton:单实例(默认):IOC容器启动时会调用方法创建对象并放到IOC容器中,以后每次获取的就是直接从容器中拿出的同一个bean。
- prototype:IOC容器启动时,IOC容器不会调用方法创建对象,而是每次获取的时候才会调用方法创建对象。
- request:主要针对web应用,递交一次请求创建一个实例。
- session:同一个session创建一个实例。
@lazy懒加载
在被标注为Bean的方法上可以使用@lazy,懒加载主要针对单实例,默认情况下,Bean在IOC容器启动时就被创建并加入到容器中,而使用懒加载,容器启动的时候不创建对象,当第一次使用Bean的时候才被创建。
@Conditional条件注册bean
@Condition可以按照一定条件进行判断,如果条件满足,那么就给容器注册bean
我们需要根据操作系统来判断是否注入bean,首先,我们创建一个WinCondition类,实现Spring为我们提供的Condition接口,实现其matches方法。
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取IOC容器中正在使用的BeanFactory
BeanFactory factory = context.getBeanFactory();
//获取当前环境变量
Environment environment = context.getEnvironment();
String os_name = environment.getProperty("os.name");
if (os_name.contains("Windows")) {
return true;
}
return false;
}
这样,我们就可以在配置类生成进行bean注入的方法上直接使用@Condition注解。
@Conditional(WinCondition.class)
@Bean
public Person zhangsan() {
return new Person("zhangsan",22);
}
@ComponentScan扫描规则
指定扫描范围
其value属性用于指定包扫描范围
value= {"base.controller"}
扫描过滤器
includeFilters和excludeFilters属性可以对扫描进行过滤,其进行过滤的范围是value所指定的范围。
默认情况下,该注解的一个属性useDefaultFilters将会扫描指定包下被标注为@Component、@Controller、@Service、@Repository的类,如果设置useDefaultFilters=false,那么,默认扫描策略将会失效。
使用includeFilters将会在useDefaultFilters的基础上,继续添加你所需要的类
使用excludeFilters指定扫描到某个类时忽略它
@ComponentScan(value= {"cn.edu.pdsu.base.controller"},
includeFilters= {
@Filter(type=FilterType.ANNOTATION,classes= {Controller.class})
},useDefaultFilters= false)
自定义过滤规则
通过配置@Filter,我们也可以自定义过滤规则
@Filter(type=FilterType.CUSTOM,classes= {MyTypeFilter.class}
我们创建类MyTypeFilter.java,实现TypeFilter接口。
/**
* @param metadataReader:读取到当前正在扫描类的信息
* @param metadataReaderFactory:可以获取其他任何类的信息
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//获取当前类注解的信息
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
//获取当前类资源(类路径)
Resource resource = metadataReader.getResource();
//获取当前正在扫描的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
String className = classMetadata.getClassName();
System.out.println("----->"+className);
if (className.contains("User")) {//在指定包下扫描到包含User的类,也会被实例化为bean return true;
}
return false;
}
@Import注册bean
通过@Import,容器会自动注册这个组件,bean的id为全限定类名
@Import(value = {Dog.class})
我们也可以通过实现ImportSelector接口,返回需要导入到容器的组件的全类名数组,来完成bean的注册。
public class PigImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//传入全限定类名
return new String[] {"cn.edu.pdsu.base.pojo.Pig"};
}
}
@Import(value = {PigImportSelector.class})
通过实现ImportBeanDefinitionRegistrar,使用BeanDefinitionRegistry将bean注册到IOC容器中。
public class PigImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(Pig.class);
registry.registerBeanDefinition("pig", beanDefinition);
}
}
@Import(value = {PigImportBeanDefinitionRegistrar.class})
FactoryBean
通过Spring提供的FactoryBean接口,我们也可以实现bean的注册。
创建PigFactoryBean,实现FactoryBean接口
public class PigFactoryBean implements FactoryBean<Pig> {
public Pig getObject() throws Exception {
return new Pig();
}
public Class<?> getObjectType() {
return Pig.class;
}
public boolean isSingleton() {
return true;
}
}
在配置类中引入当前bean
@Bean
public PigFactoryBean pig() {
return new PigFactoryBean();
}
我们在测试中查看其类型
Object bean = ac.getBean("pig");
System.out.println(bean.getClass());//base.pojo.Pig
我们可以看到,我们已经把Pig类加载到容器中去了
Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,工厂Bean跟普通Bean不同,它所返回的对象不是指定类的一个实例,而是该工厂Bean的getObject方法所返回的对象。