仅以此记录spring学习笔记
spring框架:
spring --> IOC --> DI
Dog dog = new Dog();
IOC管理
IOC就是对bean进行管理:bean注册、实例化管理
application.xml --> <bean id = 'dog' class = "com.ca.Dog">
使用注解
IOC容器:Map
java bean实例
map.put(beanId,Bean)
多实例:仅当bean被使用的时候才创建。
单实例:创建IOC容器的时候实例bean就被创建了
@Configuration 配置类声明
告诉spring这是一个配置类
BeanId 就是配置bean的方法名
Bean可以修改自定义名@Bean("自定义名")
// 配置类 == 配置文件
@Configuration
public class MainConfig {
// 给容器中注册一个bean,类型为返回值的类型
@Bean("ABC")
public Person person() {
return new Person("yang", 13);
}
}
@ComponentScan扫描规则
指定扫描范围:
注意:使用includeFilters必须将useDefaultFilters设为false
Filter[] includeFilters() default {};//包含 Filter[] excludeFilters() default {};//排除 //例子:按照注解过滤 @ComponentScan(value = "com.enjoy.cap2",excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class})}, useDefaultFilters = true)
扫描过滤器:
Fileter的类型有:
/**
* Filter candidates marked with a given annotation.
* @see org.springframework.core.type.filter.AnnotationTypeFilter
*/
ANNOTATION,
/**
* Filter candidates assignable to a given type.
* @see org.springframework.core.type.filter.AssignableTypeFilter
*/
ASSIGNABLE_TYPE,
/**
* Filter candidates matching a given AspectJ type pattern expression.
* @see org.springframework.core.type.filter.AspectJTypeFilter
*/
ASPECTJ,
/**
* Filter candidates matching a given regex pattern.
* @see org.springframework.core.type.filter.RegexPatternTypeFilter
*/
REGEX,
/** Filter candidates using a given custom
* {@link org.springframework.core.type.filter.TypeFilter} implementation.
*/
CUSTOM
自定义过滤规则:
@Configuration
@ComponentScan(
value = "com.enjoy.cap2",
includeFilters = {
@ComponentScan.Filter(
type = FilterType.CUSTOM,
classes = {MyTypeFileter.class})
},
useDefaultFilters = false)
public class MainConfig {
// 给容器中注册一个bean,类型为返回值的类型
@Bean
public Person person() {
return new Person("yang", 13);
}
}
public class MyTypeFileter implements TypeFilter {
private ClassMetadata classMetadata;
/*
* metadataReader:读取到当前正在扫描类的信息
* metadataReaderFactory:可以获取到其他任何类的信息
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// 获取当前类注解的信息
AnnotatedTypeMetadata annotatedTypeMetadata = metadataReader.getAnnotationMetadata();
// 获取当前正在扫描的类信息
classMetadata = metadataReader.getClassMetadata();
// 获取当前类资源(类的路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->" + className);
if (className.contains("OderDao")) {
return true;
} else {
return false;
}
}
}
@Scope扫描规则
1、单实例bean
2、多实例bean
3、request和session
直接使用@Bean注解时,默认是单实例的
@Configuration
@ComponentScan
public class Cap3MainConfig {
// 给容器中注册一个bean,类型为返回值的类型 默认单实例
/*
* prototype: 多实例:IOC容器启动的时候,不会去调用方法创建对象,而是每次获取的时候才会调用方法创建对象
* singleton: 单实例(默认):IOC容器启动的时候会调用方法创建对象,并且放入IOC容器中,即IOC的Map中,以后每次获取都是从容器中拿到同一个bean
* request:主要针对web应用,递交一次请求创建一次实例
* session:同一个session创建一个实例
*/
@Scope("prototype")
@Bean
public Person person() {
return new Person("yang", 13);
}
}
@Lazy懒加载
1、什么是懒加载
2、懒加载如何获取容器中的bean
@Configuration
public class Cap4MainConfig {
// 给容器中注册一个bean,类型为返回值的类型 默认单实例
// 懒加载:主要针对单实例bean:默认在容器自启动的时候创建对象
// 懒加载:容器启动的时候,不创建对象,仅当第一次使用(获取)bean的时候才创建被初始化,可解决循环service引用问题
@Lazy
@Bean
public Person person() {
return new Person("yang", 13);
}
}
@Conditional条件注册bean
1、什么是条件注册bean
2、如何根据指定条件选择性地注册bean实例
需求:运行测试用例时,如果操作系统是windows,让lion这个对象实例化到容器中,如果是linux则让lisa实例化到容器中。
条件方法实现condition接口
示例代码
@Configuration
public class Cap5MainConfig {
@Conditional(MacCondition.class)
@Bean("lisa")
public Person lisa() {
System.out.println("给容器中添加lisa……");
return new Person("lisa", 18);
}
}
/**
* 条件匹配
*
* @param context
* <p>判断条件可以使用的上下文环境
* @param metadata
* <p>注解信息
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO 是否为windows操作系统
// 从IOC容器中获取正在使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 获取当前的环境变量,包括操作系统
Environment environment = context.getEnvironment();
// 取操作系统值,os.name是规范写法
String osName = environment.getProperty("os.name");
if (osName.contains("Mac OS X")) {
return true;
}
return false;
}
}
可以通过修改环境变量,修改osname
-Dos.name=windows
@Import注册bean
1、手动添加组件到IOC容器
2、使用ImportSelector自定义返回组件
3、使用ImportBeanDefinitionRegistroar返回自定义组件
4、FactoryBean接口实现
a、getObject()返回对象方法
b、getObjectType()返回对象类型
c、isSingleton()是否单例控制
factoryBean和BeanFactory有何区别:
factoryBean:可以把java实例Bean通过factoryBean注入到容器中。
beanFactory:从容器中获取实例化后的Bean。
示例代码
//配置类
@Configuration
@Import(value = {Dog.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class Cap6MainConfig {
// 给容器中注册组件的方式
// 1、@Bean:[导入第三方的类或包的组件],比如Person是第三方的类,需要再IOC容器中使用
// 2、包扫描+组件的标注注解(@ComponentScan: @Controller,@Service @Reponsitory @Componet),一般是针对我们自己写的类
// 3、@Import:[快速给容器导入一个组件],注意:@Bean比较简单,
// 3.1、@Import(要导入到容器中的组件):容器会自动注册这个组件,bean的id为全类名
// 3.2、ImportSelect接口:返回需要导入到容器中的组件全类名数组
// 3.3、ImportBeanDefinitionRegistrar:可以手动添加组件到IOC容器,所有Bean的注册可以使用BeanDefinitionRegistry,写MyImportBeanDefinitionRegistrar实现这个接口即可
// 3.4、使用spring提供的额FactoryBean接口(工厂bean)进行注册
@Bean("yang")
public Person person() {
System.out.println("给容器中添加yang……");
return new Person("yang", 13);
}
}
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
String[] myBean = new String[2];
myBean[0] = "com.enjoy.cap6.bean.Cat";
return myBean;
}
}
/**
* @author yangzhiji
* @create 2021-01-13 9:28 PM
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
// AnnotationMetadata:当前类的注解信息
// BeanDefinitionRegistry:BeanDefinition注册类
// 把所有需要添加到容器中的bean加入
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean bean = registry.containsBeanDefinition("com.enjoy.cap6.bean.Cat");
// 如果cat存在于容器中,那么创建Pig类加入到容器中
// 对于要注册的bean需要进行封装
if (bean) {
// 封装
RootBeanDefinition beanDefinition = new RootBeanDefinition(Pig.class);
// 注册
registry.registerBeanDefinition("Pig", beanDefinition);
}
}
}
public class MyFactoryBean implements FactoryBean<Tiger> {
@Override
public Tiger getObject() throws Exception {
return new Tiger();
}
@Override
public Class<?> getObjectType() {
return Tiger.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
什么是Bean的生命周期
Bean的生命周期值Bean创建-->初始化-->销毁的过程
我们可以自定义Bean初始化和销毁方法
容器在Bean进行到当前生命周期的时候,来调用自定义的初始化和销毁方法
生命周期-初始化与销毁1
1、制定初始化init-method方法
2、指定销毁destroy-method方法
注:
对于单实例的bean,可以正常调用初始化和销毁方法
对于多实例的bean,容器只负责初始化,但不会管理bean,容器关闭时不会调用销毁方法
populateBbean (property) //属性赋值
initionlation(bean)//初始化
CGLIB可以实例化对象,原理是动态代理
@Configuration
public class Cap7MainConfigOflifeCycle {
@Bean("yang")
public Person person() {
System.out.println("给容器中添加yang……");
return new Person("yang", 13);
}
@Bean(initMethod = "init", destroyMethod = "destroy")
public Dog dog() {
return new Dog();
}
}
生命周期-初始化与销毁2
1、实现InitializingBean接口的afterPropertiesSet()方法,当beanFactory创建好对象,且把bean所有属性设置好之后,才会调用这个方法,相当于初始化方法。
2、实现disposableBean的destroy方法,当bean销毁时,,会把单实例bean进行销毁。
@Component
public class Cat implements InitializingBean, DisposableBean {
public Cat() {
System.out.println("给容器中添加cat。。。。");
}
public void init() {
System.out.println("cat初始化方法。。。");
}
@Override
public void destroy() {
System.out.println("实现DisposableBean销毁方法。。。");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("实现InitializingBean创建bean之后执行的方法。。");
}
}
生命周期-初始化与销毁3
可以使用JSR250规范(JAVA规范)定义的两个注解来实现:
@PostConstruct:在Bean创建完成,且属于赋值完成之后进行初始化,属于JDK规范的注解。
@Predestroy:在bean将被移除之前进行通知,在容器销毁之前进行清理工作
@Component
public class Tiger {
public Tiger() {
System.out.println("给容器中添加Tiger。。。。");
}
@PostConstruct
public void init() {
System.out.println("Tiger初始化方法。。。");
}
@PreDestroy
public void destroy() {
System.out.println("Tiger销毁方法。。。");
}
}
生命周期-BeanPostProcessor
bean的后置处理器,在bean初始化之前调用进行拦截,在bean初始化前后进行一些处理工作,使用BeanPostProcessor如何控制Bean的生命周期?实现BeanPostProcessor接口的两个方法即可:
1、postProcessBeforeInitialization()
2、postProcessAfterInitialization()
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// 返回一个传过来的对象
// 初始化方法调用之前进行后置处理工作
// 什么时候调用它:init-method = init之前调用
System.out.println("postProcessBeforeInitialization..." + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..." + beanName);
return bean;
}
}
spring可以针对方法进行拦截增强
BeanPostProcessor源码初步分析
使用BeanPostProcessor如何控制Bean的生命周期