SPRING注解驱动开发-雷神课程超详细笔记

SPRING注解驱动开发-雷神课程超详细笔记

时间:2021-03-21


2022-04-06更新:最近翻起一年多前写的笔记复习,还是收获颇多,很多当时无法理解的知识现在慢慢能理解了,可能是工作一年的经验?也可能是源码看多了把很多细节都记下了,哈哈。

spring核心概念 di和ioc。spring 认为所有的组件应放在容器中,组件间的依赖可自动装配

注解版 spring作为ioc容器的一些基本使用

AnnotationConfigApplicationContext //注解版用的spring容器对象
applicationContext.getBeanDefinitionNames();//容器中定义的bean名称
String[] names = applicationContext.getBeanNamesForType(Person.class);//获取容器中指定类型的bean组件的名字

使用配置类,代替配置文件:

通过标注@Configuration注解,声明注解类

通过@bean注解在方法上,注册bean
使用@scope来指定bean的作用范围

singleton和prototype

单实例下,ioc容器启动就会创建bean对象,放到容器中

多实例下,主动获取bean的时候,才创建对象

懒加载

scope为单实例,默认主动创建

可以手动设置为懒加载,使用@lazy

@conditional 通过条件来注册bean

这个注解可放在类上,也可以放在方法上

这个特性,springboot的底层大量使用

基本使用

public class MyCondition implements Condition {
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        Environment environment = context.getEnvironment();
        BeanDefinitionRegistry registry = context.getRegistry();
        return false;
    }
}

@Conditional({MyCondition.class})
通过componentScan配置包扫描

includeFilters excludeFilters可以配置过滤扫描

举个例子

@ComponentScan(basePackages = {"bean","controller"},excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})})
//按照注解的方式排除,排除bean包下,标注了Controller这个注解的类
@import 给容器中快速导入组件

有三种使用方式

最普通的class对象
@Import({Color.class})//导入组件
//id默认是全类名
importSelector

实现这个接口,返回需要导入的组件的全类名

public class MyImportSelector implements ImportSelector {

    // 返回值数组,是要导入到容器中组件的全类名
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[0];
    }
}
ImportBeanDefinitionRegistrar

实现这个接口,直接拿registry对象,给容器中注册对象

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean res = registry.containsBeanDefinition("person");
        if (!res) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class);
            registry.registerBeanDefinition("person",beanDefinition);
        }
    }
}
factoryBean

实现这个接口来导入bean

在spring整合其他技术的时候,这个特性用的非常多

public class MyFactoryBean implements FactoryBean {
//注册到容器中的时候,调用getObject方法,实际注册的不是MyFactoryBean,而是此方法的返回值
    public Object getObject() throws Exception {
        return new Person();
    }

    public Class<?> getObjectType() {
        return null;
    }

    public boolean isSingleton() {
        return false;
    }
}
bean的生命周期
初始化 和 销毁 方法

init

destroy

//Person类。。。。
public void init(){
    System.out.println("init is executed .....");
}
public void destroy(){
    System.out.println("destroy is executed .....");
}
//---------
@Bean(initMethod = "init",destroyMethod = "destroy")
@Scope
public Person person(){
    return new Person();
}

note 多实例的bean,容器只能创建bean,不会管理bean,不会调destroy

使用intializingBean和disposableBean
public class Color implements InitializingBean, DisposableBean {
    public void destroy() throws Exception {
        System.out.println("destroy.....");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("init......");
    }
}
beanPostProcessor的方式

这种方式在spring中大量使用,重点

bean的后置处理器,在bean的初始化前后做处理工作

public interface BeanPostProcessor {
    
    //Apply this BeanPostProcessor to the given new bean instance before any bean initialization callbacks (like InitializingBean's afterPropertiesSet or a custom init-method). 
    //初始化之前调
    	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    //Apply this BeanPostProcessor to the given new bean instance after any bean initialization callbacks (like InitializingBean's afterPropertiesSet or a custom init-method). 
    //初始化之后调
    	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
//----------------------------------------------
public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..." + beanName+" -->" + bean);
        //返回的bean可原样返回,也可以包装一些返回
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..." + beanName+" -->" + bean);
        //返回的bean可原样返回,也可以包装一些返回
        return bean;
    }
}
beanPostProcessor的工作原理

分析源码:

从容器创建的refresh方法的finishBeanFactoryInitialization中开始切入

比较关键的几个环节

//类 AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {
 //.......   
}
//给bean进行属性赋值
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    //.........................
}

//note 先populateBean后才进行初始化bean

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    //........
    //逻辑简单写一下
    //1 
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    //2 
    invokeInitMethods(beanName, wrappedBean, mbd);
    //3
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}


	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}
beanPostProcessor在spring中大量应用

SPRING注解驱动开发-雷神课程超详细笔记_第1张图片

重点的几个

  • ApplicationContextAwareProcessor

  • InitDestroyAnnotationBeanPostProcessor

    注解@postConstruct和@PreDestroy与这个有关

  • AutowiredAnnotationBeanPostProcessor

spring底层的大量操作,包括bean赋值,注入其他组件,@autowired,生命周期注解,@Async xxxx

都是通过beanPostProcessor的方式来实现的

bean的赋值
@value
// 1 基本数值
@Value("zhangsan")
private String name;
// 2 spel: #{}
@Value("#{20-12}")
private String age;
// 3 ${} 取出配置文件中的值
//3.1首先在配置类中配置
@PropertySource(value = {"classpath:/person.properties"})
public class MainConfig {
}
//3.2 然后普通的组件就可以用了
@Value(${person.name})
private String name;


自动装配 @Autowired

spring利用依赖注入DI,完成对ioc容器中各个组件依赖关系的赋值

@Autowired 注入的基本规则
  • 默认优先按照类型去容器中找对应的组件

  • 如果找到多个相同类型的组件,再将属性名称作为组件id去容器中找

  • @Qualifier(BeanId)明确指出要装配的bean

  • 自动装配默认必须要在容器中找到依赖,否则报错;可通过属性required = false取消这个特性

  • 这个注解可以在的位置:构造器,参数,方法,属性

//标注在方法上
//spring创建容器的时候会调用此方法,方法中自定义参数,从ioc容器中获取
@Autowired
public void setCar(Car car) {
    this.car = car;
}
//标注在构造器上
//ioc容器中的组件,默认是用无参构造器创建对象,然后再进行赋值操作
//但是使用这种方式,则在创建阶段,寻找组件的依赖关系。
@Autowired
public Boss(Car car){
    this.car = car;
}

//注意,如果只有一个有参构造器,则有参构造器的@Autowired可以省略,也能自动装配参数位置的组件
public Boss(Car car){
    this.car = car;
}

//注意,@Bean方式注入组件,方法参数的值可以直接从容器中获取,不需要@Autowired
@Bean
public Boss boss(Car car) {
    return new Boss(car);
}



  • @Autowired不写的默认规则如上例子,并大量使用不写的方式自动装配依赖
如何使用spring底层的组件,如ApplicationContext BeanFactory etc…

一句话:使用xxxxxAware

/** Marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method. 
Actual method signature is determined by individual subinterfaces, but should typically consist of just one void-returning method that accepts a single argument.
Note that merely implementing Aware provides no default functionality. 
**/
public interface Aware {

}

自定义组件实现xxxxAware,在创建对象的时候,会调用接口规定的方法,注入相关组件。

可参考:ApplicationContextAware、EmbeddedValueResolverAware

每一个xxxxAware,都有其对应的XXXXprocessor

ApplicationContextAware的注入原理
  • ApplicationContextAwareProcessor是BeanPostProcessor,所以其会有BeanPostProcessor的特性,在创建组件的时候给组件赋值,即调用postProcessBeforeInitialization、postProcessAfterInitialization
  • 最关键的逻辑写在postProcessBeforeInitialization中,如下
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
   AccessControlContext acc = null;
//等待创建的bean,如果实现了如下接口,就通过反射方式调用接口中的方法
   if (System.getSecurityManager() != null &&
         (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
               bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
               bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
      acc = this.applicationContext.getBeanFactory().getAccessControlContext();
   }

   if (acc != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
         @Override
         public Object run() {
            invokeAwareInterfaces(bean);
            return null;
         }
      }, acc);
   }
   else {
      invokeAwareInterfaces(bean);
   }

   return bean;
}

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基本使用

spring提供的根据当前环境,动态切换一系列组件的功能

环境:开发、测试、生产

@Configuration
public class ProfileConfig {
    @Profile("test")
    @Bean("dataSourceTest")
    public DataSource dataSourceTest(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        // ....省略配置数据源的过程....
        return dataSource;
    }
    @Profile("dev")
    @Bean("dataSourceDev")
    public DataSource dataSourceDev(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        // ....省略配置数据源的过程....
        return dataSource;
    }
    @Profile("prod")
    @Bean("dataSourceProd")
    public DataSource dataSourceProd(){
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        // ....省略配置数据源的过程....
        return dataSource;
    }
}
// 激活环境
//1 使用命令行参数
//-Dspring.profiles.active=test
// ------------------------
// 2 代码方式
//手动选择profile
applicationContext.getEnvironment().setActiveProfiles("test","dev");
applicationContext.register(ProfileConfig.class);
applicationContext.refresh();

AOP面向切面编程

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

底层原理就是 动态代理

aop的相关名词

  • 业务逻辑类
  • 切面类
  • 通知 —> 通知方法 @Before @After @AfterReturning @AfterThrowing
  • 切点
  • 。。。。。
// 切面 和 不同种类的通知(方法)
@Aspect
public class LogAspect {
    
    @Pointcut("execution(public void com.hhdd.Service.MyService.*(..))")
    public void pointcut(){}
    @Before("pointcut()")
    public void logStart(){
        System.out.println("业务开始,记录日志");
    }
    @After("pointcut()")
    public void logEnd(){
        System.out.println("业务结束,记录日志");

    }
    @AfterReturning("pointcut()")
    public void logReturn(){
        System.out.println("业务返回,记录日志");

    }
    @AfterThrowing("pointcut()")
    public void logException(){
        System.out.println("业务异常,记录日志");
    }
}

  • 开启aop:将业务类和切面类加入容器中,且配置类上配置@EnableAspectJAutoProxy

    AOP原理

    注解@EnableAspectJAutoProxy
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
     //...............   
    }
    
    AspectJAutoProxyRegistrar.class
//这个类是一个 ImportBeanDefinitionRegistrar,可以自定义注册组件
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    //关键是注册了这个东西 AspectJAnnotationAutoProxyCreator
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
	// ....
}
简单记录下registerAspectJAnnotationAutoProxyCreatorIfNecessary的过程
  1. 先看容器中是否有了定义为
String AUTO_PROXY_CREATOR_BEAN_NAME =
      "org.springframework.aop.config.internalAutoProxyCreator";

的组件。有则直接取,没有就创建bean定义信息,注册到组件里头

  1. 创建bean定义信息并注册到容器中
//这里的cls是org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
组件AnnotationAwareAspectJAutoProxyCreator
继承关系

SPRING注解驱动开发-雷神课程超详细笔记_第2张图片

本质上是一个后置处理器

重点关注后置处理器的处理过程和BeanFactoryAware

重点方法
  1. setBeanFactory
  2. postProcessBeforeInstantiation
  3. postProcessAfterInitialization
setBeanFactory过程

这个方法来源于接口BeanFactoryAware,在实例化bean的时候,setBeanFactory就会被调用。跟踪这个过程,可以看到实例化类AnnotationAwareAspectJAutoProxyCreator的过程。

通过debug形式,分析方法调用栈

// 1.类AnnotationConfigApplicationContext
refresh();
// 2.类AbstractApplicationContext
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 3.类PostProcessorRegistrationDelegate (非完整代码,仅截取关键部分)
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext){
	//3.1 按优先级分类容器中的postProcessor
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
	List<String> orderedPostProcessorNames = new ArrayList<String>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
	}
    //3.2 按顺序注册PostProcessor
    // First, register the BeanPostProcessors that implement PriorityOrdered.
    //....
    // Next, register the BeanPostProcessors that implement Ordered.
    //...
    // Now, register all regular BeanPostProcessors.
    ....
}
//3.2在getBean的过程中,其实包括了实例化这个bean。此前,容器中只包含bean的定义信息,BeanDefiniton
//ppname 在这里是org.springframework.aop.config.internalAutoProxyCreator
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
//3.3实例化bean的过程。。。。
//getBean --> doGetBean --> doGetBean
//重点说下doGetBean过程
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    // Eagerly check singleton cache for manually registered singletons.
    //检查下cache里是不是有了这个单实例bean
    Object sharedInstance = getSingleton(beanName);
	//有好几个缓存。。。singletonObjects earlySingletonObjects singletonFactories
	//--------------------------------	
	// Check if bean definition exists in this factory.
	//.............
	// Create bean instance.
	//getSingleton --> singletonFactory.getObject() --> createBean(String beanName, RootBeanDefinition mbd, Object[] args) --> doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
	//note:createBean中有一个环节需要注意一下
	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

	//doCreateBean代码截取
		// Initialize the bean instance.
		//先填充属性,再初始化bean
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}
	//initializeBean开始
	//如果类是这些的aware的实现,其中的方法就会在这里被执行
	invokeAwareMethods(beanName, bean);
	private void invokeAwareMethods(final String beanName, final Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
        //最后,就是setBeanFactory的调用
	}

到这里,进入setBeanFactory的流程分析结束

后续呢?继续从initializeBean()方法往下执行

initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd){
    //1 invokeAwareMethods(beanName, bean);
    //....................
    
    //2 调postProcessor中的PostProcessorsBeforeInitialization
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    
    //3 调初始化方法,像init-method和initializingBean接口中的afterPropertiesSet()
    invokeInitMethods(beanName, wrappedBean, mbd);
    
    //4 调postProcessor中的PostProcessorsAfterInitialization
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    
    //到此,实例化bean完成,即AnnotationAwareAspectJAutoProxyCreator创建完成
}

类AbstractAdvisorAutoProxyCreator的setBeanFactory方法分析

public void setBeanFactory(BeanFactory beanFactory) {
   super.setBeanFactory(beanFactory);
   if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
      throw new IllegalArgumentException(
            "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
   }
   initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   super.initBeanFactory(beanFactory);
   if (this.aspectJAdvisorFactory == null) {
       //创建aspectJAdvisorFactory
      this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
   }
    //重新包装一层
   this.aspectJAdvisorsBuilder =
         new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
postProcessBeforeInstantiation

这个方法来自接口InstantiationAwareBeanPostProcessor

分析进入这个方法的过程

//类AbstractApplicationContext
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 遍历获取容器中所有bean,依次创建对象
getBean --> doGetBean --> getSingleton --> createBean
//重点createBean()
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {

	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    //后置处理器先尝试返回对象
	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
	if (bean != null) {
		return bean;
	}
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	//。。。。。。。。。。。。。。。
	Class<?> targetType = determineTargetType(beanName, mbd);
	if (targetType != null) {
        //1.。。。。
		bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
		if (bean != null) {
			//2.。。。。。。
            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
		}
        
	}
   
}
//applyBeanPostProcessorsBeforeInstantiation的过程
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
			if (result != null) {
				return result;
			}
		}
	}
	return null;
}
//最后就进入了postProcessBeforeInstantiation

组件AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor,也就是说,容器中任何一个(不严谨)bean在实例化的时候,会被这个组件拦截,都会先通过这个组件,让这个组件尝试直接返回bean。

类AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation做了什么

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   Object cacheKey = getCacheKey(beanClass, beanName);

   if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   // Create proxy here if we have a custom TargetSource.
   // Suppresses unnecessary default instantiation of the target bean:
   // The TargetSource will handle target instances in a custom fashion.
   if (beanName != null) {
      TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
      if (targetSource != null) {
         this.targetSourcedBeans.add(beanName);
         Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
         Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
         this.proxyTypes.put(cacheKey, proxy.getClass());
         return proxy;
      }
   }

   return null;
}
postProcessAfterInitialization

进入到这一步,说明是从doCreateBean中进入的

类AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (!this.earlyProxyReferences.contains(cacheKey)) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}
//最终返回增强过的代理对象
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
    	// 重点
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //重点
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

如何判断切点类型的advisor是否可以作用于当前的bean,在AopUtil类的canApply中做处理

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
 		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;   
}
protected Object createProxy(
      Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

   if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
   }

   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);

   if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }

   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }

   return proxyFactory.getProxy(getProxyClassLoader());
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
         throw new AopConfigException("TargetSource cannot determine target class: " +
               "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

两种形式的代理对象

  • JdkDynamicAopProxy
  • ObjenesisCglibAopProxy

spring可以自动决定

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
         throw new AopConfigException("TargetSource cannot determine target class: " +
               "Either an interface or a target is required for proxy creation.");
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

在自己下的example代码中,MyService经过springAop的增强,容器中的对象,实际上是经过cglib增强过的代理对象。以后只要是从容器中获取MyService组件的,都是获取到代理对象。

AOP拦截器链

容器中保存的组件是增强后的的代理对象,对象里保存了详细信息(包括增强器,目标对象等等)

调用代理对象的方法时,会经过aop拦截器链的处理

intercept

CglibAopProxy的intercept

  • 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  • 没有拦截器链,直接执行目标方法,有则
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
获取拦截器链过程
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
      Advised config, Method method, Class<?> targetClass) {

   // This is somewhat tricky... We have to process introductions first,
   // but we need to preserve order in the ultimate list.
   List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
   Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
   boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
   AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

   for (Advisor advisor : config.getAdvisors()) {
      if (advisor instanceof PointcutAdvisor) {
         // Add it conditionally.
         PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
         if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
             //包装成MethodInterceptor
            MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
            MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
            if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
               if (mm.isRuntime()) {
                  // Creating a new object instance in the getInterceptors() method
                  // isn't a problem as we normally cache created chains.
                  for (MethodInterceptor interceptor : interceptors) {
                     interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                  }
               }
               else {
                  interceptorList.addAll(Arrays.asList(interceptors));
               }
            }
         }
      }
      else if (advisor instanceof IntroductionAdvisor) {
         IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
         if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
            Interceptor[] interceptors = registry.getInterceptors(advisor);
            interceptorList.addAll(Arrays.asList(interceptors));
         }
      }
      else {
         Interceptor[] interceptors = registry.getInterceptors(advisor);
         interceptorList.addAll(Arrays.asList(interceptors));
      }
   }

   return interceptorList;
}
拦截器链调用过程

以MyService类的doSomething()调用做例子

其调用经过的拦截器链,如下图所示

// 待补充…

SPRING注解驱动开发-雷神课程超详细笔记_第3张图片

public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();
   }

   Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
      // Evaluate dynamic method matcher here: static part will already have
      // been evaluated and found to match.
      InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
      if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
         return dm.interceptor.invoke(this);
      }
      else {
         // Dynamic matching failed.
         // Skip this interceptor and invoke the next in the chain.
         return proceed();
      }
   }
   else {
      // It's an interceptor, so we just invoke it: The pointcut will have
      // been evaluated statically before this object was constructed.
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回再执行

通过拦截器链机制,保证通知方法和目标方法的执行顺序。

spring中的事务

基本使用

dao类

@Repository
public class AccountDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<Map<String, Object>> select() {
        String sql = "select * from account";
        List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);
        return results;
    }

    @Transactional
    public void insert() {
        String sql = "insert into account (name,money) values('huanghedidi',18.5)";
        int count = jdbcTemplate.update(sql);
        System.out.println("更新了" + count + "条记录");
    }
}

config类

@Configuration
@ComponentScan(basePackages = {"com.hhdd.dao", "com.hhdd.service"})
@EnableTransactionManagement
public class TXConfig {

    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://192.168.153.8:3306/ssm");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        return jdbcTemplate;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource);
        return dataSourceTransactionManager;
    }
}

spring事务的原理

使用了注解@EnableTransactionManagement,这个注解引入了@Import(TransactionManagementConfigurationSelector.class)

类TransactionManagementConfigurationSelector导入的组件,如下

//根据adviceMode决定要导入的组件
protected String[] selectImports(AdviceMode adviceMode) {
   switch (adviceMode) {
      case PROXY:
         return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
      case ASPECTJ:
         return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
      default:
         return null;
   }
}

//---------------
//adviceMode来源于类EnableTransactionManagement
//默认是PROXY
	/**
	 * Indicate how transactional advice should be applied. The default is
	 * {@link AdviceMode#PROXY}.
	 * @see AdviceMode
	 */
	AdviceMode mode() default AdviceMode.PROXY;

引入的AutoProxyRegistrar又注册了一些bean

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   boolean candidateFound = false;
   Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
   for (String annoType : annoTypes) {
      AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
      if (candidate == null) {
         continue;
      }
      Object mode = candidate.get("mode");
      Object proxyTargetClass = candidate.get("proxyTargetClass");
      if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
            Boolean.class == proxyTargetClass.getClass()) {
         candidateFound = true;
         if (mode == AdviceMode.PROXY) {
             //注册AutoProxyCreator
            AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
            if ((Boolean) proxyTargetClass) {
               AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
               return;
            }
         }
      }
   }
   if (!candidateFound) {
      String name = getClass().getSimpleName();
      logger.warn(String.format("%s was imported but no annotations were found " +
            "having both 'mode' and 'proxyTargetClass' attributes of type " +
            "AdviceMode and boolean respectively. This means that auto proxy " +
            "creator registration and configuration may not have occurred as " +
            "intended, and components may not be proxied as expected. Check to " +
            "ensure that %s has been @Import'ed on the same class where these " +
            "annotations are declared; otherwise remove the import of %s " +
            "altogether.", name, name, name));
   }
}
//这里的class是InfrastructureAdvisorAutoProxyCreator.class
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
      BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
      if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
         int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
         int requiredPriority = findPriorityForClass(cls);
         if (currentPriority < requiredPriority) {
            apcDefinition.setBeanClassName(cls.getName());
         }
      }
      return null;
   }
   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

事务实现的重点就是这个组件:InfrastructureAdvisorAutoProxyCreator

InfrastructureAdvisorAutoProxyCreator

继承结构如下

SPRING注解驱动开发-雷神课程超详细笔记_第4张图片

可以看到和aop原理中导入的组件AnnotationAwareAspectJAutoProxyCreator是类似的

关键的是实现了InstantiationAwareBeanPostProcessor接口,容器在实例化bean的时候,会被这个组件拦截,这个组件可以尝试直接返回bean(代理对象)

ProxyTransactionManagementConfiguration

这个是一个配置类

给容器注册一些组件

  • BeanFactoryTransactionAttributeSourceAdvisor
  • TransactionAttributeSource
  • TransactionInterceptor 是一个MethosInteceptor

关键的是类TransactionInterceptor 的invokeWithinTransaction方法

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);
   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

名称上,与BeanPostProcessor有点像

调用的时机:在BeanFactory标准初始化后调用

/**
 * Modify the application context's internal bean factory after its standard
 * initialization. All bean definitions will have been loaded, but no beans
 * will have been instantiated yet. This allows for overriding or adding
 * properties even to eager-initializing beans.
 * @param beanFactory the bean factory used by the application context
 * @throws org.springframework.beans.BeansException in case of errors
 */
//所有的bean定义已经加载,但是bean还没有实例化的时候
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

执行过程分析

  1. // Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors(beanFactory);
    
  2. private static void invokeBeanFactoryPostProcessors(
          Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    	//遍历容器中所有的BeanFactoryPostProcessor执行其中的方法
       for (BeanFactoryPostProcessor postProcessor : postProcessors) {
          postProcessor.postProcessBeanFactory(beanFactory);
       }
    }
    

典型的例子 BeanDefinitionRegistryPostProcessor接口

这个接口在BeanFactoryPostProcessor基础上,新增了一个方法

/**
 * Modify the application context's internal bean definition registry after its
 * standard initialization. All regular bean definitions will have been loaded,
 * but no beans will have been instantiated yet. This allows for adding further
 * bean definitions before the next post-processing phase kicks in.
 * @param registry the bean definition registry used by the application context
 * @throws org.springframework.beans.BeansException in case of errors
 */
//在bean定义还没有被加载的时候执行
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

优先于BeanFactoryPostProcessor执行

ApplicationListener

监听容器中发布的事件,事件驱动开发

基本使用

定义事件

public class MyApplicationEvent extends ApplicationEvent {
    /**
     * Create a new ApplicationEvent.
     *
     * @param source the object on which the event initially occurred (never {@code null})
     */
    public MyApplicationEvent(Object source) {
        super(source);
    }
}

监听事件

public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("收到的事件是:" + event);
    }
}

发布事件

public void test1() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
    MyApplicationEvent myApplicationEvent = new MyApplicationEvent("自定义事件");
    applicationContext.publishEvent(myApplicationEvent);
}
原理
ContextRefreshedEvent事件

refresh()

finishRefresh();

// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
//事件发布的流程
//1 获取事件多播器:getApplicationEventMulticaster()
//2 派发事件
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            //有线程池,可支持异步执行
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(new Runnable() {
					@Override
					public void run() {
						invokeListener(listener, event);
					}
				});
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

MyApplicationEvent事件

自己调用publishEvent方法

过程和上面是类是的,都是得到多播器,用多播器遍历所有的listener来回调listener的onApplicationEvent(event)逻辑

事件多播器ApplicationEventMulticaster

创建的时机

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

@EventListener

基本使用
@Service
public class MyService {
    @EventListener(classes = {ApplicationEvent.class})
    public void doSomething(ApplicationEvent applicationEvent){
        System.out.println("doSomething.... "+applicationEvent);
    }
}
原理

使用EventListenerMethodProcessor来解析方法上的@EventListener

EventListenerMethodProcessor实现了接口SmartInitializingSingleton

SmartInitializingSingleton
public interface SmartInitializingSingleton {

   /**
    * Invoked right at the end of the singleton pre-instantiation phase,
    * with a guarantee that all regular singleton beans have been created
    * already. {@link ListableBeanFactory#getBeansOfType} calls within
    * this method won't trigger accidental side effects during bootstrap.
    * 

NOTE: This callback won't be triggered for singleton beans * lazily initialized on demand after {@link BeanFactory} bootstrap, * and not for any other bean scope either. Carefully use it for beans * with the intended bootstrap semantics only. */ //调用时机:所有单实例bean已经被初始化完成的时候调用 void afterSingletonsInstantiated(); }

触发流程分析

  • ioc容器创建并refresh

  • finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean

  • beanFactory.preInstantiateSingletons();

    public void preInstantiateSingletons() throws BeansException {
       if (this.logger.isDebugEnabled()) {
          this.logger.debug("Pre-instantiating singletons in " + this);
       }
    
       // Iterate over a copy to allow for init methods which in turn register new bean definitions.
       // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
       List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    
       // Trigger initialization of all non-lazy singleton beans...
       for (String beanName : beanNames) {
          RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
          if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
             if (isFactoryBean(beanName)) {
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                   isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                      @Override
                      public Boolean run() {
                         return ((SmartFactoryBean<?>) factory).isEagerInit();
                      }
                   }, getAccessControlContext());
                }
                else {
                   isEagerInit = (factory instanceof SmartFactoryBean &&
                         ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                   getBean(beanName);
                }
             }
             else {
                getBean(beanName);
             }
          }
       }
    
       // Trigger post-initialization callback for all applicable beans...
        //在这里调用...............
       for (String beanName : beanNames) {
          Object singletonInstance = getSingleton(beanName);
          if (singletonInstance instanceof SmartInitializingSingleton) {
             final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
             if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                   @Override
                   public Object run() {
                      smartSingleton.afterSingletonsInstantiated();
                      return null;
                   }
                }, getAccessControlContext());
             }
             else {
                smartSingleton.afterSingletonsInstantiated();
             }
          }
       }
    }
    

spring容器创建过程

这个是重点

Refresh

流程分析

  • prepareRefresh();刷新前预处理工作

    • InitPropertySources();初始化一些属性,留给子类使用
    • getEnvironment().validateRequiredProperties(); 进行属性校验
    • this.earlyApplicationEvents = new LinkedHashSet();保存早期的事件
  • obtainFreshBeanFactory();获取BeanFactory

    • refreshBeanFactory();刷新BeanFactory,设置id
    • ConfigurableListableBeanFactory beanFactory = getBeanFactory();在this()时候已经创建了BeanFactory,这个时候将其返回
  • prepareBeanFactory(beanFactory);//BeanFactory的预准备工作

    • 设置类加载器,表达式解析器…
    • 添加部分BeanPostProcessor,例如ApplicationContextAwareProcessor
    • 设置忽略的一些自动装配接口,例如EnvironmentAware等等
    • 注册可以解析的自动装配,能在任何组件中自动注入,例如BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
    • 注册一些组件,例如StandardEnvironment、systemProperties、systemEnvironment
  • postProcessBeanFactory(beanFactory);子类通过重写此方法来进行设置

-----------------------------以上是beanFactory的创建以及准备工作------------------------------

  • invokeBeanFactoryPostProcessors(beanFactory);

    • BeanFactoryPostProcessor在BeanFactory准备完成后,开始执行
    • 两个接口:BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor
    • 先处理BeanDefinitionRegistryPostProcessor,调用postProcessBeanDefinitionRegistry(registry)
    • 再处理BeanFactoryPostProcessor,调用postProcessBeanFactory(beanFactory)
  • registerBeanPostProcessors(beanFactory);

    • 重点BeanPostProcessor:DestructionAwareBeanPostProcessor、InstantiationAwareBeanPostProcessor、SmartInstantiationAwareBeanPostProcessor、MergedBeanDefinitionPostProcessor
    • 不同的BeanPostProcessor的执行时机是不一样的
    • 注册BeanPostProcessorChecker
    • 按照BeanPostProcessor的优先级顺序,注册BeanPostProcessor
    • 最后,再一次注册internal BeanPostProcessors,这个指的是类型为MergedBeanDefinitionPostProcessor。为什么说再一次呢?因为前面按优先级注册的时候,可能已经注册过了
    • 注册ApplicationListenerDetector组件,为了放在chain的最后一个位置。用于监听ApplicationListener的组件注册,如果是则放到ApplicationContext的applicationListeners中
  • initMessageSource();mvc中初始化messageSource(用于国际化等等)

  • initApplicationEventMulticaster();事件多播器

  • onRefresh();留给子类进行重写

  • registerListeners();

    • 将容器中的每个ApplicatonListener添加到事件多播器中
    • 派发早期已经在容器中注册的事件
  • finishBeanFactoryInitialization(beanFactory);**重要!!!**初始化所有剩下的bean

    • beanFactory.preInstantiateSingletons();
    • 获取bean的定义信息
    • 当bean是单实例,非懒加载,则开始实例化bean
    • getBean() --> doGetBean(name, null, null, false);
    • doGetBean的创建细节
      • 标上已经创建的标记
      • 获取bean定义的dependsOn,即依赖其他的bean。如果有,则需要先getBean依赖的组件
      • 启动单实例bean的创建流程
        • Object bean = resolveBeforeInstantiation(beanName, mbdToUse);让BeanPostProcessor尝试返回代理对象
          • 提前执行InstantiationAwareBeanPostProcessor的逻辑
        • 如果没有返回代理对象,则正式进入创建流程
        • 如果是最普通的方式注入的bean,会通过反射获取构造器对象来实例化bean
        • applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);应用后置处理器
        • populateBean(beanName, mbd, instanceWrapper);
          • 赋值之前,拿到InstantiationAwareBeanPostProcessor,调用postProcessAfterInstantiation方法
          • 赋值之前,拿到InstantiationAwareBeanPostProcessor,调用postProcessPropertyValues方法
          • 最后,applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) 为属性利用setter方法进行赋值
        • initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)初始化bean
          • 执行invokeAwareMethods(beanName, bean)
          • 执行applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
          • 执行invokeInitMethods(beanName, wrappedBean, mbd);这里说的初始化方法,指的是init-method和initlizingBean接口中的afterPropertySet()这类的方法
          • 执行applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        • 注册bean的销毁方法
      • 成功创建bean并返回
      • 添加到缓存,即singletonObjects中,是一个map。ioc容器,指的就是这一个个的map
    • 当所有的单实例bean都实例化完成后,遍历所有bean,找出其中类型为SmartInitializingSingleton的bean,并执行afterSingletonsInstantiated()
  • finishRefresh();

    • 执行initLifecycleProcessor();与生命周期有关
    • 执行getLifecycleProcessor().onRefresh();拿到生命周期相关的处理器,回调onRefresh()
    • 执行publishEvent(new ContextRefreshedEvent(this));发布容器刷新事件
spring容器创建小结
  • spring容器创建的时候,先会包保存注册进来的Bean的定义信息。方式有xml和注解
  • spring合适时机创建bean
    • getBean方式创建bean实例
  • 后置处理器:每一个bean创建过程,会被这些处理器拦截,增强功能
  • 事件驱动模型:ApplicationListener

spring web部分

Servlet容器(如Tomcat)启动的时候,会扫描应用和每一个jar包中的ServletContainerInitializer的实现,如过找到,就会执行onStartup

关于这个实现类,必须绑定在,META-INF/services/javax.servlet.ServletContainerInitializer中,文件内容就是ServletContainerInitializer实现类的全类名

servlet3.0整合springMVC

springMVC的jar包,包含了ServletContainerInitializer接口的实现类:SpringServletContainerInitializer

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    //这个方法的作用是扫描类路径中所有实现了WebApplicationInitializer接口的类,并调用其中的onStartup方法,同时这个方法接受一个参数,servletContext
    //原理就是servlet3.0会自动执行这个类,且将@HandlesTypes(WebApplicationInitializer.class)指定的class作为参数传入onStartup方法
  public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {

		List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

		if (webAppInitializerClasses != null) {
			for (Class<?> waiClass : webAppInitializerClasses) {
				// Be defensive: Some servlet containers provide us with invalid classes,
				// no matter what @HandlesTypes says...
				if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
						WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
					try {
						initializers.add((WebApplicationInitializer) waiClass.newInstance());
					}
					catch (Throwable ex) {
						throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
					}
				}
			}
		}

		if (initializers.isEmpty()) {
			servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
			return;
		}

		servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
		AnnotationAwareOrderComparator.sort(initializers);
		for (WebApplicationInitializer initializer : initializers) {
			initializer.onStartup(servletContext);
		}
	}  
    
}
WebApplicationInitializer

这个接口的一个实现类AbstractDispatcherServletInitializer

public void onStartup(ServletContext servletContext) throws ServletException {
   super.onStartup(servletContext);
   registerDispatcherServlet(servletContext);
}

//------------父类------------------------
	protected void registerContextLoaderListener(ServletContext servletContext) {
		WebApplicationContext rootAppContext = createRootApplicationContext();
		if (rootAppContext != null) {
			ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
			listener.setContextInitializers(getRootApplicationContextInitializers());
			servletContext.addListener(listener);
		}
		else {
			logger.debug("No ContextLoaderListener registered, as " +
					"createRootApplicationContext() did not return an application context");
		}
	}

//-------------------
protected void registerDispatcherServlet(ServletContext servletContext) {
		String servletName = getServletName();
		Assert.hasLength(servletName, "getServletName() must not return empty or null");
		//创建一个web的ioc容器
		WebApplicationContext servletAppContext = createServletApplicationContext();
		Assert.notNull(servletAppContext,
				"createServletApplicationContext() did not return an application " +
				"context for servlet [" + servletName + "]");
		//创建dispatcherServlet
		FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
		dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
		//添加到web容器中
		ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
		Assert.notNull(registration,
				"Failed to register servlet with name '" + servletName + "'." +
				"Check if there is another servlet registered under the same name.");

		registration.setLoadOnStartup(1);
		registration.addMapping(getServletMappings());
		registration.setAsyncSupported(isAsyncSupported());

		Filter[] filters = getServletFilters();
		if (!ObjectUtils.isEmpty(filters)) {
			for (Filter filter : filters) {
				registerServletFilter(servletContext, filter);
			}
		}

		customizeRegistration(registration);
	}

实现类AbstractAnnotationConfigDispatcherServletInitializer

常见spring容器,这里是注解形式的spring容器
protected WebApplicationContext createRootApplicationContext() {
   Class<?>[] configClasses = getRootConfigClasses();
   if (!ObjectUtils.isEmpty(configClasses)) {
      AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
      rootAppContext.register(configClasses);
      return rootAppContext;
   }
   else {
      return null;
   }
}
总结

注解方式启动springMVC,可通过继承AbstractAnnotationConfigDispatcherServletInitializer,实现其中的抽象方法,指定DispathcerServlet的配置信息

根容器配置示例

Configuration
@ComponentScan(basePackages = {"com.hhdd"}, excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
},useDefaultFilters = false)
public class RootConfig {


}

web容器配置示例

@Configuration
@ComponentScan(basePackages = {"com.hhdd"}, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
public class AppConfig {


}

实现AbstractAnnotationConfigDispatcherServletInitializer示例

public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    //获取根容器的配置类 父容器(spring配置文件)
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{RootConfig.class};
    }

    //获取web容器的配置类 子容器(springMVC配置文件)
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{AppConfig.class};
    }

    /**
     * 给dispatcherServlet配置映射信息
     *
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

springMVC注解版使用

自定义mvc需要的组件

通过继承WebMvcConfigurerAdapter,配合注解@EnableWebMvc

通过覆盖父类的方法来自定义组件

servlet的异步使用

示例

@WebServlet(value = "/async", asyncSupported = true)
public class HelloAsyncServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("主线程:" +Thread.currentThread() + "开始执行,时间:" +System.currentTimeMillis());
        //开启异步模式
        AsyncContext asyncContext = req.startAsync();
        //业务逻辑以异步形式进行处理
        asyncContext.start(() -> {
            try {
                System.out.println("副线程:" +Thread.currentThread() + "开始执行,时间:" +System.currentTimeMillis());
                sayHello();
                asyncContext.complete();
                ServletResponse response = asyncContext.getResponse();
                response.getWriter().write("HelloAsyncServlet.....");
                System.out.println("副线程:" +Thread.currentThread() + "结束执行,时间:" +System.currentTimeMillis());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        System.out.println("主线程:" +Thread.currentThread() + "结束执行,时间:" +System.currentTimeMillis());
    }

    private void sayHello() throws Exception {
        System.out.println(Thread.currentThread()+"processing....");
        Thread.sleep(3000);
    }
}
//---------------控制台输出-----------------------
主线程:Thread[http-nio-8080-exec-4,5,main]开始执行,时间:1617550229321
主线程:Thread[http-nio-8080-exec-4,5,main]结束执行,时间:1617550229329
副线程:Thread[http-nio-8080-exec-5,5,main]开始执行,时间:1617550229329
Thread[http-nio-8080-exec-5,5,main]processing....
副线程:Thread[http-nio-8080-exec-5,5,main]结束执行,时间:1617550232330
springMVC中的异步处理
@Controller
public class HelloAsyncController {
    @ResponseBody
    @RequestMapping("/async/hello")
    public Callable<String> sayHello() {

        System.out.println("主线程:" +Thread.currentThread() + "开始执行,时间:" +System.currentTimeMillis());
        Callable<String> callable = () -> {
            System.out.println("副线程:" +Thread.currentThread() + "开始执行,时间:" +System.currentTimeMillis());
            Thread.sleep(3000);
            System.out.println("副线程:" +Thread.currentThread() + "结束执行,时间:" +System.currentTimeMillis());
            return "HelloAsyncController.....";
        };
        System.out.println("主线程:" +Thread.currentThread() + "结束执行,时间:" +System.currentTimeMillis());
        return callable;
    }
}

//---------------控制台输出-----------------------
//springmvc用一个异步线程池来处理异步请求
主线程:Thread[http-nio-8080-exec-4,5,main]开始执行,时间:1617551494128
主线程:Thread[http-nio-8080-exec-4,5,main]结束执行,时间:1617551494129
副线程:Thread[MvcAsync1,5,main]开始执行,时间:1617551494138
副线程:Thread[MvcAsync1,5,main]结束执行,时间:1617551497139

springmvc对异步请求的处理过程

  • 将callable提交到TaskExecutor,使用一个隔离线程进行执行
  • DispatcherServlet和所有的Filter退出web容器的线程,但是response保持打开的状态
  • Callable返回结果,springmvc将请求重新派发给容器,恢复之前的处理
  • springmvc继续进行视图渲染的流程(从头开始,请求,渲染…)
DeferredResult的使用

示例

@ResponseBody
@RequestMapping("/createOrderStep1")
public DeferredResult createOrderStep1() {
    DeferredResult<Object> deferredResult = new DeferredResult<Object>();
    //保存到queue中
    queue.saveDeferredResult(deferredResult);
    return deferredResult;
}

@ResponseBody
@RequestMapping("/createOrderStep2")
public String createOrderStep2() {
    DeferredResult deferredResult = queue.getDeferredResult();
    String uuid = UUID.randomUUID().toString();
    deferredResult.setResult(uuid);
    return ("createOrderStep2..." + uuid);
}

场景说明:请求接入的时候,result的处理时间要很长,可以先找个queue保存起来(可以是消息队列等中间件)。其他线程在queue中获取到这个result,并且其他线程处理完业务逻辑后调用result.setResult()方法,先前被hold住的线程就可以继续放行。

你可能感兴趣的:(spring,Java,java,web,spring)