@Configuration : 配置类 == 配置文件,告诉Spring这是一个配置类
@ComponentScan(value=“com.atguigu”,excludeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})
@ComonentScan value : 指定要扫描的包(这个注解可以定义多个)
excludeFilters = Filter[] : 指定扫描的时候按照什么规则排除那些组件
includeFilters = Filter[] : 指定扫描的时候只需要包含那些组件
useDefaultFilters = false : 表示去掉默认扫描
FilterType.ANNOTATION : 按照注解类型 例如 : Controller.class
FilterType.ASSIGNABLE_TYPE : 按照给定的类型 例如 : UserService.class
FilterType.ASPECTJ : 使用ASPECTJ表达式
FilterType.REGEX : 使用正则指定
FilterType.CUSTOM : 使用自定义规则
自定义规则需要实现TypeFilter接口
public class MyTypeFilter implements TypeFilter {
/**
metadataReader : 读取到的当前正则扫描的类的信息
metadataReaderFactory : 可以获取到其他任何类的信息
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
// 获取当前类注解的信息
AnnotationMetadata annotationMetadate = metadataReader.getAnnontationMetadata();
// 获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
// 获取这个类名
String className = classMetadata.getClassName();
// 自定义匹配规则
if(className.contains(“er”)) {
return true;
}
return false;
}
}
@ComponentScans(
value {
@ComponentScan(value=“com.atguigu”,excludeFilters = {
@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
}, useDefaultFilters = false)
}
) : 里面可以定义多个@ComponentScan
@Bean : 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Scope("") : 表示这个对象或者这个bean的创建作用域范围(调整作用域).
prototype : 多实例的,ioc容器时并不会调用方法创建对象放在容器中.每次获取的时候才会调用方法创建对象.
singleton : 单实例的(默认值),ioc容器启动会调用方法创建对象放到ioc容器中.以后每次获取就是直接从容器(map.get())中拿.
request : 同一次请求创建一个实例
session : 同一个session创建一个实例
@Lazy : 懒加载
单实例bean,默认在容器启动的时候创建对象.
懒加载: 容器启动不创建对象,第一次调用(获取)Bean创建对象,并初始化.
@Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean(可以放在@Bean上,或者类上)
例如 :
//放在类上统一设置
// 类中组件统一设置,满足当前条件,这个类中配置的所有bean注册才能生效.
@Conditional({WindowsCondition.class})
@Configuration
//实现接口Condition
public class LinuxCondition implements Condition {
/**
*/
public boolean matchs(CondititContext context, AnnotatedTypeMetadata metadada) {
// 是否linux系统
// 1. 能获取到ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 2.获取类加载器
ClassLoader classLoader = context.getClassLoader();
// 3.获取当前环境信息
Environment environment = context.getEnvironment();
// 4.获取到bean定义的注册类(可以判断容器中的bean注册情况,也可以给容器中注册bean)
BeanDefinitionRegistry registry = context.getRegistry();
// 判断容器中是否包含bean
boolean definition = registry.containsBeanDefinition(“persion”);
String property = environment.getProperty(“os.name”);
if (property.contains(“linux”)){
return true;
}
return false;
}
}
// 获取bean名称
String[] namesForType = applicatinContext.getBeanNamsForType();
// 动态获取环境变量的值,获取容器运行环境例如 : windows,liunx
ConfigurableEnvironment environment = applicationContext.getEnvironment();
// 获取操作系统的名称
String property = environment.getProperty(“os.name”);
给容器中注册组件 :
1 : 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
2 : @Bean[导入的第三方包里面的组件]
3 : @Import[快速给容器中导入一个组件]
@Import(要导入到容器中的组件 例如 : Color.class) : 方在类上,导入组件,容器中就会自动注册这个组件,id默认是组件的全类名(也可以导入多个组件)
(2) ImportSelector : 返回需要导入的组件的全类名数组.
例如 :
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector {
// 返回值,就是导入到容器中的组件全类名
// AnnotationMetadata : 当前标注@Import注解的类的所有注解信息
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 方法不要返回null值
return new String[];
}
}
@Import({Color.class,Red.class,MyImportSelector.class})
(3) ImportBeanDefinitionRegistrar : 手动注册Bean到容器中
例如 :
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
// AnnotationMetadata : 当前类的注解信息
// BeanDefinitionRegistry : BeanDefinitionRegistry注册类;
// 把所有需要添加到容器中的bean : 调用 BeanDefinitionRegistry.registryBeanDefinition手工注册进来
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
// 通过bean名称,判断bean是否在容器中
booean definition = registry.containsBeanDefinition(“red”);
boolean definition1 = registry.containsBeanDefinition(“blue”);
if (definition && definition1) {
// 指定bean定义信息 : (Bean的类型,Bean…)
RootBeanDefinition bean = new RootBeanDefinition(RainBow.class);
// 注册一个Bean,指定Bean名
registry.registryBeanDefinition(“rainBow”, bean);
}
}
}
4 : 例子 :
// 创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean {
// 返回一个Color对象,这个对象会添加到容器中
@Override
public Color getObject() throws Exception {
return new Color();
}
public Class> getObjectType() {
return Color.class;
}
//是单例?
//true : 这个bean是单例,在容器中保存一份
//false : 多实例,每次获取都会创建一个新的bean
@Override
public boolean isSingleton() {
return false
}
}
@Bean
public ColorFactoryBean getBean() {
return new ColorFactoryBean();
}
public void test() {
//工厂Bean获取的是调用getObject创建的对象;实际上获取的是Color对象
Object bean2 = applicatinContext.getBean(“colorFactoryBean”);
//这个是获取的ColorFactoryBean对象,因为在FactoryBean接口中定义了一个字符串,表示以&开头的就是获取实现FactoryBean接口的对象
Object bean3 = applicatinContext.getBean("&colorFactoryBean");
}
Bean的生命周期
bean创建 – 初始化 – 销毁的过程
容器管理bean的生命周期 :
我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁的方法
构造(对象创建)
单实例 : 在容器启动的时候创建对象
多实例 : 在每次获取的时候创建对象
BeanPostProcessor.postProcessBeforeInitialization
初始化 :
对象创建完成,并赋值好,调用初始化方法…
BeanPostProcessor.postProcessInitialization
销毁 :
单实例 : 容器关闭的时候
多实例 : 容器不会管理者bean,容器不会调用销毁方法.
遍历得到容器中所有的BeanPostProcessor : 挨个执行beforeInitialization,一旦返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessBeforeInitialization
BeanPostProcessor的原理
populateBean(beanName, mdb, instanceWrapper) : 给bean进行属性赋值
initializeBean
{
appliyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
}
例如 :
public class Dog{
public Dog() {
System.out.println("");
}
//对象创建并赋值之后调用
@PostConstruct
public void init() {
System.out.println(“11”);
}
//容器移除对象之前
@PreDestroy
public void detory(){
}
}
4) : BeanPostProcessor[interface] : bean后置处理器;
在bean初始化前后进行一些处理工作;
postProcessBeforeInitialization : 在初始化之前工作
postProcessInitialization : 在初始化之后工作
Spring底层对BeanPostProcessor的使用 :
bean赋值,注入其他组件,@Autowired,生命周期注解功能。@Async, xxx BeanPostProcessor;
@Value : 给属性赋值。
自动装配 :
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值;
激活方式 :
(1) : 使用命令行动态参数 : 在虚拟机参数位置加载 -Dspring.profiles.active=test
(2) :代码的方式激活某种环境。
(3) : 没有标注环境标识的bean在任何环境下都是加载的。
例如 :
AnnotationConfigApplicationContext applicatinContext = new AnnontationConfigApplicationContext();
//1。创建一个applicationContext
//2. 设置需要激活的环境
applicatinContext.getEnvironment().setActiveProfiles(“dev”);
//3.注册主配置类
applicatinContext.registry(MainConfigOrProfile.class);
//4.启动刷新容器
applicatinContext.refresh();
深圳网站建设https://www.sz886.com