Spring注解驱动开发


文章来源:https://www.bilibili.com/video/BV1ME411o7Uu?p=4
大纲
image

组件注册

@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

  1. @ComponentScan扫描的注解
  2. @Bean
  3. @Import

具体用法

  1. @Import默认是类的群路径
    @Import({BookNot.class, Book.class})
  2. @ImportSelector
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        String className = importingClassMetadata.getClassName();
        //自定义选择注入的类
        return new String[0];
    }
}
  1. 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

image

//赋值
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原生注解
    1. 默认按照byName去装配
    2. 不能支持@Primary、@Qualifier 和(required = false)
  • @Inject JSR330 java原生注解
    1. 跟@Autowired一样,不支持required = false
    2. 需要导入依赖

方法 构造器自动装配

  1. 方法位置
@Autowired
public void setBookNot(BookNot bookNot) {
    this.bookNot = bookNot;
}
  1. 构造器
//默认在ioc容器中的组件,启动会默认调用无参构造创建对象,在进行初始化赋值
@Component
public class Boss {

    @Autowired
  //如果组件只有一个有参构造器 @Autowired可以省略
    public Boss(BookNot bookNot) {
        this.bookNot = bookNot;
    }

但是这种情况容易造成循环依赖问题

  1. 方法上标注

    @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为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;

  1. 加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境

  2. 写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生

    
    /**
     *
     *  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;
    }
    

    }

    
    
    

激活环境

  1. 使用命令行,在虚拟机参数位置加载 -Dspring.profiles.active=test

  2. 使用代码的方式激活某种环境

    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

程序运行期间,动态的将某段代码切入到指定方法指定位置进行运行的编程方式。

  1. @Before
  2. @After
  3. @AfterRetuning
  4. @AfterThrowing
  5. @Around:将函数标记为在切入点覆盖的方法之前执行的通知。
  6. @Aspect:告知Spring 本类是切面类
  7. @EnableAspectJAutoProxy:开启自动代理
  8. 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的创建

    1. 获取IOC已定义好的BPP

    2. 添加其他BBP

    3. 对后置处理进行简单的排序以及分离

    4. 优先注册priorityOrderedPostProcessors、orderedPostProcessors

    5. 注册bbp,实际就是getBean()

      ​ 1).创建bean的实例

      ​ 2).populateBean 属性赋值

      ​ 3).初始化bean

      ​ 4).创建成功

    6. 将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

  1. @EnableTransactionManagement利用TransactionManagementConfigurationSelector给容器中导入组件
  2. 默认是AdviceMode.PROXY 因为会导入AutoProxyRegistrar和ProxyTransactionManagementConfiguration

AutoProxyRegistrar 会注入一个 InfrastructureAdvisorAutoProxyCreator:利用后置处理器在对象创建以后,对对象进行包装,返回一个代理对象。代理对象执行方法利用拦截器链进行

ProxyTransactionManagementConfiguration

  1. 注册事务增强器 解析事务注解信息
@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);
    }
}
  1. 在BeanFactory中找到BeanFactoryPostProcessor的组件
  2. 在初始化其他组件之前执行

@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注册,执行的方法是一样的 只是优于执行
image

applicationListener

监听容器中发生的事件,事件驱动模式开发 观察者模式引用

//发布事件
context.publishEvent(new ApplicationEvent(new Integer(1)) {

});

https://www.bilibili.com/video/BV1ME411o7Uu?p=42

事件发布流程

  1. 获取事件的多播器getApplicationEventMulticaster()

  2. 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);
          }
       }
    }
    
  3. 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);
       }
    }
    
    1. 回调方法
    @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

  1. 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

  1. 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);
        }
     }
  }

@EventListener

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值