文章来源:https://www.bilibili.com/video/BV1ME411o7Uu?p=4
大纲
![image](https://i-blog.csdnimg.cn/blog_migrate/2f8fb8755f47eb9e41171cee5b507612.png)
组件注册
@Configuration
用于定义配置类,被定义的类会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
一般和@bean一起使用
@Configuration就相当于Spring配置文件中的<beans />标签,里面可以配置bean
@Bean相当于Spring配置文件中的<bean/>标签可以在Spring容器中注入一个bean
@ComponentScan
//相当于之前
<context:component-scan/>
@ComponentScan(basePackages ={"spring.java"},
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookNot.class,Person.class})},
//是否开启默认扫描 @Controller,@Service,@Repository,@Component
useDefaultFilters = false,
excludeFilters={
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)}
)
public class MyConfig {
- @ComponentScan自定扫描路径下边带有@Controller,@Service,@Repository,@Component注解的类到spring容器中
- includeFilters指定要扫描的包
- excludeFilters指定要排除的
- 可以自定义指定某个类是否被扫描
- @componentScan 指定多个扫描
FilterType
//常用
FilterType.ANNOTATION:注解
FilterType.ASSIGNABLE_TYPE:自定义
//不太常用
FilterType.ASPECTJ:按照Aspectj的表达式,基本上不会用到
FilterType.REGEX:按照正则表达式
FilterType.CUSTOM:自定义规则
FilterType.CUSTOM
编写自定义类实现TypeFilter
public class MyFilterType implements TypeFilter {
//metadataReader
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//metadataReader:the metadata reader for the target class 当前类信息
//metadataReaderFactory:a factory for obtaining metadata readers 其他类信息
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类的资源信息,例如:类的路径等信息
Resource resource = metadataReader.getResource();
//获取当前正在扫描的类名
String className = classMetadata.getClassName();
//自定义你想要要加入容器的
return false;// true表示加入进去
}
}
@Scope
spring默认bean都是单例的singleton
- singleton:全局有且仅有一个实例,启动时会调用方法放入ioc容器中,后面直接从容器中拿
- prototype:启动不放入ioc容器中,每次获取Bean的时候会有一个新的实例
- request:request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
- session: session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
@Lazy
表示用到的时候初始化
@Conditional
- 按照一定的条件进行判断,满足条件,给容器中注册bean
//其他版本的 @ContionalOnClass 等等 其实也是实现了Condition接口
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//自己的逻辑判断
return false;
}
}
- 可以作用在方法上,也可以放在类上
@Configuration
@Conditional({MyCondition.class})
public class MyConfig1 {
@Bean(name = "person")
// @Scope("singleton")
// @Lazy
public Person person1(){
return new Person("1",12);
}
@Bean("bill")
// @Conditional({MyCondition.class})
public Person person(){
return new Person("conditional",12);
}
}
- 多个自定义condition
C1&C2
@import
给容器中加bean
- @ComponentScan扫描的注解
- @Bean
- @Import
具体用法
- @Import默认是类的群路径
@Import({BookNot.class, Book.class}) - @ImportSelector
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
String className = importingClassMetadata.getClassName();
//自定义选择注入的类
return new String[0];
}
}
- ImportBeanDefinitionRegistrar
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//扫描注解
Map<String, Object> annotationAttributes = importingClassMetadata
.getAnnotationAttributes(ComponentScan.class.getName());
String[] basePackages = (String[]) annotationAttributes.get("basePackages");
//扫描类
ClassPathBeanDefinitionScanner scanner =
new ClassPathBeanDefinitionScanner(registry, false);
TypeFilter helloServiceFilter = new AssignableTypeFilter(Book.class);
scanner.addIncludeFilter(helloServiceFilter);
scanner.scan(basePackages);
//也可以直接调用registry注册bean
// registry.registerBeanDefinition();
}
}
@Configuration
// @Conditional({MyCondition.class})
@Import({BookNot.class, Book.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class MyConfig1 {
FactoryBean
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new Person();
}
@Override
public Class<?> getObjectType() {
return Person.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
- 默认获取的是工厂bean创建的对象
- 使用‘&’获取工厂本身bean
//获取的是getObject实例
Object myFactoryBean = context.getBean("myFactoryBean");
//获取的是myFactoryBean实例
//public interface BeanFactory {
//String FACTORY_BEAN_PREFIX = "&";
Object myFactoryBean1 = context.getBean("&myFactoryBean");
Bean生命周期
了解Spring容器下的生命周期,可以更好的帮我们理解AOP、spring循环依赖(Spring三级缓存)
- 传统的bean生命周期很简单 实例化-使用-销毁
@Bean指定初始化和销毁
Spring只会管理单实例的bean,多实例只会创建,剩下交给使用者
@Bean(initMethod = "init",destroyMethod = "destory")
public Person person() {
return new Person();
}
InitializingBean和DisposableBean
public class Person implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("destroy--------------");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet--------------");
}
Constructor >InitializingBean>ininMethod>DisposableBean>destroyMethod
AbstractAutowireCapableBeanFactory.invokeInitMethods
@PostConstruct和@PreDestory
作用于方法上
Constructor >PostConstruct>InitializingBean>ininMethod>PreDestory>DisposableBean>destroyMethod
@BeanPostProcessor
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
正确的:Constructor>postProcessBeforeInitialization>@PostConstruct>InitializingBean>ininMethod>postProcessAfterInitialization>@PreDestory>DisposableBean>destroyMethod
自己写的有问题的:后面看了spring整体流程再来找问题
Constructor>@PostConstruct>InitializingBean>ininMethod>postProcessBeforeInitialization>postProcessAfterInitialization>@PreDestory>DisposableBean>destroyMethod
@BeanPostProcessor原理
https://www.bilibili.com/video/BV1ME411o7Uu?p=16#sepwin=VIDEO
//赋值
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
//initializeBean
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//before
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//after
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
@BeanPostProcessor在Spring底层使用
ApplicationContextAwareProcessor
AutowiredAnnotationBeanPostProcessor
组件赋值
@Value
//1.基本数值
//2.SPEL #{}
//3. ${} 配置文件的值
@Value("zhangsan")
String name;
@Value("#{20-2}")
Integer age;
@PropertySource
@PropertySources
@PropertySource("classpath:/person.properties")
@Configuration
public class MyConfigPropertyValues {
@Bean
public MyConfigPropertyValuesBean myConfigPropertyValuesBean(){
return new MyConfigPropertyValuesBean();
}
}
person.name=nihao
public class MyConfigPropertyValuesBean {
//1.基本数值
//2.SPEL #{}
//3. ${} 配置文件的值
@Value("zhangsan")
String name;
@Value("#{20-2}")
Integer age;
@Value("${person.name}")
String names;
组件注入
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值。
@Autowired
可参考: https://www.jianshu.com/p/2f1c9fad1d2d
- 优先按照类型去容器中找对应的组件(byType)
- 如果找到相同的,在将属性的名称作为组件的id去容器中(byName)
- 配合 @Qualifier 指定按照名称去装配 bean。
- 自动装配前,如果没有对应的组件会报错,@Autowired(required = false)
- @Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
如果注册一个bean,在配置类重新Bean 只会找配置类的第一个Bean
@Resource @Inject
- @Resource JSR250 java原生注解
- 默认按照byName去装配
- 不能支持@Primary、@Qualifier 和(required = false)
- @Inject JSR330 java原生注解
- 跟@Autowired一样,不支持required = false
- 需要导入依赖
方法 构造器自动装配
- 方法位置
@Autowired
public void setBookNot(BookNot bookNot) {
this.bookNot = bookNot;
}
- 构造器
//默认在ioc容器中的组件,启动会默认调用无参构造创建对象,在进行初始化赋值
@Component
public class Boss {
@Autowired
//如果组件只有一个有参构造器 @Autowired可以省略
public Boss(BookNot bookNot) {
this.bookNot = bookNot;
}
但是这种情况容易造成循环依赖问题
-
方法上标注
@Bean public Boss boss(BookNot bookNot){ Boss boss = new Boss(); boss.setBookNot(bookNot); return boss; }
Aware接口原理
ApplicationContextAware
实现Aware接口,将Spring底层组件注入自定的方法中
@Component
public class MyApplicationContextAware implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext=null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
System.out.println(applicationContext);
}
@Override
public void setBeanName(String name) {
System.out.println(name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println(resolver);
}
@Override
public String toString() {
return "MyApplicationContextAware{" +
"applicationContext=" + applicationContext +
'}';
}
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
@Profile
pring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
-
加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
-
写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生
/** * * Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能; * * local dev test 数据源 * @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件 * * @version 1.0 * @description * @date 2020/7/3 21:26 */ // @Profile("local") 只有指定的环境 配置类才会生效 @PropertySource("classpath:db.properties") @Configuration public class MyConfigProfile implements EmbeddedValueResolverAware {
@Value("${db.user}") String user; @Value("${db.password}") String password; String driver; // @Profile("local") @Bean("local") public DataSource local() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/40028"); dataSource.setPassword(password); dataSource.setUser(user); dataSource.setDriverClass(driver); return dataSource; } @Profile("dev") @Bean("dev") public DataSource dev() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/kmyx"); dataSource.setPassword(password); dataSource.setUser(user); dataSource.setDriverClass(driver); return dataSource; } @Profile("test") @Bean("test") public DataSource test() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/24"); dataSource.setPassword(password); dataSource.setUser(user); dataSource.setDriverClass(driver); return dataSource; } @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { String driver = resolver.resolveStringValue("${db.driver}"); this.driver=driver; }
}
激活环境
-
使用命令行,在虚拟机参数位置加载 -Dspring.profiles.active=test
-
使用代码的方式激活某种环境
public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); //这里不能使用有参构造 //设置环境 context.getEnvironment().setActiveProfiles("dev","test"); context.register(MyConfigProfile.class); context.refresh(); String[] beanNamesForType = context.getBeanNamesForType(DataSource.class); for (String s : beanNamesForType) { System.out.println(s); } }
AOP
程序运行期间,动态的将某段代码切入到指定方法指定位置进行运行的编程方式。
- @Before
- @After
- @AfterRetuning
- @AfterThrowing
- @Around:将函数标记为在切入点覆盖的方法之前执行的通知。
- @Aspect:告知Spring 本类是切面类
- @EnableAspectJAutoProxy:开启自动代理
- joinPoint一定是参数的第一位
- 切面类
//告诉spring 本类是切面类
@Aspect
public class LogAspect {
//抽取切入点公共表达式
@Pointcut("execution(public int spring.java.aop.MathCalculator.divide(int,int))")
public void cut() {
}
//前置
@Before("cut()")
public void logStart(JoinPoint joinPoint) {
//获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
Signature signature = joinPoint.getSignature();
//获取传入目标方法的参数对象
Object[] objects = joinPoint.getArgs();
//获取被代理的对象
Object target = joinPoint.getTarget();
//获取代理对象
Object aThis = joinPoint.getThis();
System.out.println("logStart");
}
//外部类引用本类方法
//后置
@After("spring.java.aop.LogAspect.cut()")
public void logEnd(JoinPoint joinPoint) {
System.out.println("logEnd");
}
//返回
@AfterReturning(value = "cut()",returning = "result")
public void log(Object result) {
System.out.println("log--return:"+result);
}
//异常
@AfterThrowing(value = "cut()",throwing = "exception")
public void logError(Exception exception) {
System.out.println("logError");
}
}
-
配置类
@EnableAspectJAutoProxy @Configuration public class MyConfigAop { @Bean public MathCalculator mathCalculator(){ return new MathCalculator(); } @Bean public LogAspect logAspect(){ return new LogAspect(); } }
原理分析
给容器中注册了什么组件,这个组件什么时候工作。
利用AspectJAutoProxyRegistrar自定义给容器中注入Bean
internalAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
->AspectJAwareAdvisorAutoProxyCreator
->AbstractAdvisorAutoProxyCreator
->AbstractAutoProxyCreator
->SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
AnnotationAwareAspectJAutoProxyCreator
AbstractAutoProxyCreator实现了后置处理器、aware接口
AbstractAdvisorAutoProxyCreator.setBeanFactory()
AbstractAdvisorAutoProxyCreator.initBeanFactory()
AspectJAwareAdvisorAutoProxyCreator没有后置方法以及aware
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()
-
IOC容器创建
-
注册配置类
-
refresh()
-
registerBeanPostProcessors:注册bean后置处理器 拦截bean的创建
-
获取IOC已定义好的BPP
-
添加其他BBP
-
对后置处理进行简单的排序以及分离
-
优先注册priorityOrderedPostProcessors、orderedPostProcessors
-
注册bbp,实际就是getBean()
1).创建bean的实例
2).populateBean 属性赋值
3).初始化bean
4).创建成功
-
将bbp注册到BeanFactory
private static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { for (BeanPostProcessor postProcessor : postProcessors) { beanFactory.addBeanPostProcessor(postProcessor); } }
-
-
finishBeanFactoryInitialization(beanFactory):完成BeanFactory初始化,创建剩下的单实例bean
总结(待复习)
- @EnableAspectJAutoProxy开启AOP
- 注册一个组件AnnotationAwareAspectJAutoProxyCreator,是一个后置处理器
声明式事物
- 开启事务管理功能
- 使用@transactional
- 配置事务管理器 加入容器中
@EnableTransactionManagement
- @EnableTransactionManagement利用TransactionManagementConfigurationSelector给容器中导入组件
- 默认是AdviceMode.PROXY 因为会导入AutoProxyRegistrar和ProxyTransactionManagementConfiguration
AutoProxyRegistrar 会注入一个 InfrastructureAdvisorAutoProxyCreator:利用后置处理器在对象创建以后,对对象进行包装,返回一个代理对象。代理对象执行方法利用拦截器链进行
ProxyTransactionManagementConfiguration
- 注册事务增强器 解析事务注解信息
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
//注册事务增强器
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//解析事务注解信息
advisor.setTransactionAttributeSource(transactionAttributeSource());
//事务拦截器
advisor.setAdvice(transactionInterceptor());
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
return advisor;
}
事务拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
//事务信息
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
//事务管理器
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
TransactionInterceptor实现了MethodInterceptor
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
//获取事务相关属性
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
//获取事务管理器 先按照自定义名字获取,没有取默认 在没有 从ioc容器中获取
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
//回滚是事务管理器做的
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
//利用管理器提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
return new ThrowableHolder(ex);
}
}
finally {
cleanupTransactionInfo(txInfo);
}
}
});
// Check result: It might indicate a Throwable to rethrow.
if (result instanceof ThrowableHolder) {
throw ((ThrowableHolder) result).getThrowable();
}
else {
return result;
}
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
}
}
Spring源码分析
@BeanFactoryPostProcessor
在BeacFactory初始化标准后调用 所有bean的定义已加载到BeanFactory ,但bean的实例还没有创建
public class MyBeanFactoryPsotProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// BeanDefinition beanDefinition = beanFactory.getBeanDefinition();
int beanDefinitionCount = beanFactory.getBeanDefinitionCount();
System.out.println("工有多少个bean"+beanDefinitionCount);
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
BeanDefinition exConfig = beanFactory.getBeanDefinition("person");
System.out.println(exConfig);
}
}
- 在BeanFactory中找到BeanFactoryPostProcessor的组件
- 在初始化其他组件之前执行
@BeanDefinitionRegistryPostProcessor
在所有Bean定义信息将要被加载
优先于BeanFactory,在这里可以额外添加组件
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
//registry bean信息定义中心 beanfactory就是按照BeanDefinitionRegistry保存的每一个bean来创建实例的
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//可以在这里加入bean的定义信息
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Book.class).getBeanDefinition();
registry.registerBeanDefinition("book",beanDefinition);
System.out.println(registry.getBeanDefinitionCount());
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println(beanFactory.getBeanDefinitionCount());
}
}
源码中BeanDefinitionRegistryPostProcessor会先比BeanFactoryPostProcessor注册,执行的方法是一样的 只是优于执行
applicationListener
监听容器中发生的事件,事件驱动模式开发 观察者模式引用
//发布事件
context.publishEvent(new ApplicationEvent(new Integer(1)) {
});
https://www.bilibili.com/video/BV1ME411o7Uu?p=42
事件发布流程
-
获取事件的多播器getApplicationEventMulticaster()
-
multicastEvent派发事件
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); //获取所有的applicationListeners for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { //Executor:一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command),该方法接收一个Runable实例,它用来执行一个任务,任务即一个实现了Runnable接口的类,一般来说,Runnable任务开辟在新线程中的使用方法为:new Thread(new RunnableTask())).start(),但在Executor中,可以使用Executor而不用显示地创建线程:executor.execute(new RunnableTask()); // 异步执行 Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { //异步派发 invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }
-
invokeListener
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { doInvokeListener(listener, event); } catch (Throwable err) { errorHandler.handleError(err); } } else { doInvokeListener(listener, event); } }
- 回调方法
@SuppressWarnings({"unchecked", "rawtypes"}) private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { //多态 listener.onApplicationEvent(event); } catch (ClassCastException ex) { String msg = ex.getMessage(); if (msg == null || msg.startsWith(event.getClass().getName())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for Log logger = LogFactory.getLog(getClass()); if (logger.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } }
是不是觉得很简单,我最开始也是这么以为的。。。
getApplicationEventMulticaster
-
refresh->initApplicationEventMulticaster
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); //寻找APPLICATION_EVENT_MULTICASTER_BEAN_NAME if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { //自己new this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); //加入容器 beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }
getApplicationListeners
- refresh->registerListeners
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}