阅读前提需了解 AOP 注解开发流程:链接

一、注解 @EnableAspectJAutoProxy


在配置类中添加注解@EnableAspectJAutoProxy,便开启了 AOP(面向切面编程) 功能。此注解也是了解 AOP 源码的入口。

@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {

【1】@EnableAspectJAutoProxy 是什么?我们进入注解,查看其源码如下:发现调用 EnableAspectJAutoProxy 类,同时使用 @Import  注解向容器中导入 AspectJAutoProxyRegistrar 组件:作用是给容器中注册自定义的 Bean。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

【2】进入 AspectJAutoProxyRegistrar  类,调用 registerBeanDefinitions 中的 register...Necessary 方法注册组件。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //向容器(registry)中注入组件
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

【3】 进入 register...Necessary 方法,通过源码分析:该方法向容器中注册一个 AnnotationAwareAspectJAutoProxyCreator (支持注解模式的面向切面自动代理创建器)组件,其名称为 internalAutoProxyCreator 。需要注意的是其注册的是一个 BeanDefinition(Bean 的定义信息,并没有实例化。后续分析时会说到) 。

 1 //debug 进来后,发现cls参数的值等于 AnnotationAwareAspectJAutoProxyCreator 这个参数也是直接写死的,如下:。
2 //registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
3 @Nullable
4 private static BeanDefinition registerOrEscalateApcAsRequired(
5 Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
6
7 Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
8 //AUTO_PROXY_CREATOR_BEAN_NAME == internalAutoProxyCreator
9 //因第一次进来,所以容器中不存在 internalAutoProxyCreator
10 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
11 BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
12 if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
13 int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
14 int requiredPriority = findPriorityForClass(cls);
15 if (currentPriority < requiredPriority) {
16 apcDefinition.setBeanClassName(cls.getName());
17 }
18 }
19 return null;
20 }
21 //创建一个新的对象封装 cls
22 RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
23 beanDefinition.setSource(source);
24 beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
25 beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
26 //将封装的cls对象注册到容器中,并将名称定义为AUTO_PROXY_CREATOR_BEAN_NAME == internalAutoProxyCreator 就上上述判断的语句。
27 //此时我们就应该分析 AnnotationAwareAspectJAutoProxyCreator对象的作用
28 registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
29 return beanDefinition;
30 }

二、研究 AnnotationAwareAspectJAutoProxyCreator


此自动代理创建器的内部功能,其等价于 AOP 的主要功能。 此类的继承结构如下:

我们进入自动代理的抽象父类 AbstractAutoProxyCreator 中发现,其实现了 SmartInstantiationAwareBeanPostProcessor 后置处理器(在 bean 初始化前后做一些操作,AOP 的特点)和 BeanFactoryAware 自动装配 BeanFactory。

@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

AOP原理分析技巧:【看给容器中注册了什么组件, 这个组件什么时候工作,这个组件的功能是什么?】,研究透这些,原理也就清楚了。

我们从 AbstractAutoProxyCreator 父类向 AnnotationAwareAspectJAutoProxyCreator 子类的顺序,查看其内部关于后置处理器和自动装备的方法并加入断点:
【1】AbstractAutoProxyCreator :包含后置处理器前后的两个方法和自动装配的方法。

 1 //后置处理器相关的方法1
2 @Override
3 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
4 Object cacheKey = getCacheKey(beanClass, beanName);
5
6 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
7 if (this.advisedBeans.containsKey(cacheKey)) {
8 return null;
9 }
10 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
11 this.advisedBeans.put(cacheKey, Boolean.FALSE);
12 return null;
13 }
14 }
15
16 //后置处理器相关的方法2
17 @Override
18 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
19 if (bean != null) {
20 Object cacheKey = getCacheKey(bean.getClass(), beanName);
21 if (this.earlyProxyReferences.remove(cacheKey) != bean) {
22 return wrapIfNecessary(bean, beanName, cacheKey);
23 }
24 }
25 return bean;
26 }
27
28 //自动装备相关的方法
29 @Override
30 public void setBeanFactory(BeanFactory beanFactory) {
31 this.beanFactory = beanFactory;
32 }

【2】AbstractAdvisorAutoProxyCreator:重写了 setBeanFactory 方法。

 1 //自动装备方法
2 @Override
3 public void setBeanFactory(BeanFactory beanFactory) {
4 super.setBeanFactory(beanFactory);
5 if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
6 throw new IllegalArgumentException(
7 "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
8 }
9 initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
10 }

【3】对 2中的 initBeanFactory 方法进行了重写。

1 @Override
2 protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
3 super.initBeanFactory(beanFactory);
4 if (this.aspectJAdvisorFactory == null) {
5 this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
6 }
7 this.aspectJAdvisorsBuilder =
8 new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
9 }

三、Debug 测试类流程梳理


【1】创建 IOC 容器,传入主配置类 MainConfigOfAOP

//获取容器中的类
ApplicationContext ApplicationContext =
new AnnotationConfigApplicationContext(MainConfigOfAOP.class);

【2】调用 AnnotationConfigApplicationContext 构造器:注册配置类和刷新容器(创建容器中的所有Bean,类似于初始化容器)

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//创建对象
this();
//注册配置类
register(annotatedClasses);
//刷新容器
refresh();
}

【3】调用 refresh 方法:主要查看 registerBeanPostProcessors(beanFactory); 方法,其作用是注册 bean 后置处理器,用方便来拦截 bean 的创建。

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
....
// 注册 bean 后置处理器,用来拦截 bean 的创建
registerBeanPostProcessors(beanFactory);
....
}

【4】进入 registerBeanPostProcessors 调用的方法:先获取 IOC 容器中已经定义了的需要创建对象的所有后置处理器BeanPostProcessor(已定义:指我们在解析配置类的时候@EnableAspectJAutoProxy 会为我们注册一个 AnnotationAwareAspectJAutoProxyCreator 后置处理器的定义,包括默认的一些后置处理器的定义)例如:

上述列表中的 internalAutoProxyCreator 后置处理器,就是我们分析 @EnableAspectJAutoProxy 时注入的那个处理器。后置处理的注册分为以下三种情况:
  ■ 优先注册实现了 PriorityOrdered(优先级)接口的 BeanPostProcessors;
  ■ 其次注册实现了Ordered 接口的 BeanPostProcessors;
  ■ 注册所有常规 Beanpstprocessors;
internalAutoProxyCreator 后置处理器实现了 Ordered 接口。分析代码可知:【根据 bean定义名称 internalAutoProxyCreator 从 beanFactory 中获取注入的后置处理器】调用的方法 = beanFactory.getBean(ppName, BeanPostProcessor.class);

 1 public static void registerBeanPostProcessors(
2 ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
3 //获取ioc容器中已经定义了的需要创建对象的所有 BeanPostProcessor
4 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
5
6 //也会注意一些其他后置处理器,bean 是在 beanPostProcessor 实例化期间创建的,即 bean 不适合由所有 beanPostProcessors 处理。这个其实不重要,可以省略...
7 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
8 beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
9 //判断哪些后置处理器配置了优先级
10 for (String ppName : postProcessorNames) {
11 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
12 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
13 priorityOrderedPostProcessors.add(pp);
14 if (pp instanceof MergedBeanDefinitionPostProcessor) {
15 internalPostProcessors.add(pp);
16 }
17 }else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
18 orderedPostProcessorNames.add(ppName);
19 }else {
20 nonOrderedPostProcessorNames.add(ppName);
21 }
22 }
23 // 优先注册实现了 PriorityOrdered(优先级) 的 BeanPostProcessors
24 sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
25 registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
26
27 // 其次注册实现了Ordered 接口的 BeanPostProcessors.
28 List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
29 for (String ppName : orderedPostProcessorNames) {
30 //根据 bean定义的名称internalAutoProxyCreator 从 beanFactory 中获取注入的后置处理器
31 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
32 orderedPostProcessors.add(pp);
33 if (pp instanceof MergedBeanDefinitionPostProcessor) {
34 internalPostProcessors.add(pp);
35 }
36 }
37 sortPostProcessors(orderedPostProcessors, beanFactory);
38 registerBeanPostProcessors(beanFactory, orderedPostProcessors);
39
40 // 注册所有常规beanpstprocessors。
41 List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
42 for (String ppName : nonOrderedPostProcessorNames) {
43 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
44 nonOrderedPostProcessors.add(pp);
45 if (pp instanceof MergedBeanDefinitionPostProcessor) {
46 internalPostProcessors.add(pp);
47 }
48 }
49 registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
50
51 // 最后,重新注册所有内部beanpstprocessors。
52 sortPostProcessors(internalPostProcessors, beanFactory);
53 registerBeanPostProcessors(beanFactory, internalPostProcessors);

【5】进入上述所说的 beanFactory.getBean(ppName, BeanPostProcessor.class); 方法如下:因第一次进入容器,因此获取不到实例。会通过 getSingleton 方法创建 BeanPostProcessor 的实例,并保存到容器中。

 1 @Override
2 public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
3 return doGetBean(name, requiredType, null, false);
4 }
5
6
7 //上述方法内部调用的是 doGetBean(name, requiredType, null, false); 代码如下:
8 @SuppressWarnings("unchecked")
9 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
10 @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
11 //因为第一次获取,容器中不存在此实例。因此 sharedInstance==null
12 Object sharedInstance = getSingleton(beanName);
13 if (sharedInstance != null && args == null) {
14 ...
15 }else {
16 // 创建 bean 实例
17 if (mbd.isSingleton()) {
18 sharedInstance = getSingleton(beanName, () -> {
19 try {
20 return createBean(beanName, mbd, args);
21 }catch (BeansException ex) {
22 destroySingleton(beanName);
23 throw ex;
24 }
25 });
26 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
27 }
28 }

【6】创建 internalAutoProxyCreator 的 AnnotationAwareAspectJAutoProxyCreator 实例。步骤如下:

//1、创建bean的实例
createBean(beanName, mbd, args);
//2、给Bean 的各属性赋值
populateBean(beanName, mbd, instanceWrapper);
//3、初始化 bean ,比较重要,因为后置处理器就是在此前后进行工作的
exposedObject = initializeBean(beanName, exposedObject, mbd);

【7】重点是:初始化 initializeBean 方法,查看实现的步骤如下:

 1 //1、调用 invokeAwareMethods 处理Aware 接口的方法回调,beanName=internalAutoProxyCreator 实现了 BeanAware 接口
2 invokeAwareMethods(beanName, bean);
3 //2、应用后置处理器 BeforeInitialization
4 applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
5 //3、执行自定义的初始化方法
6 invokeInitMethods(beanName, wrappedBean, mbd);
7 //4、执行后置处理器的 After方法
8 applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
9
10 //下面是上述方法的具体实现
11
12 //1、invokeAwareMethods 实现如下:
13 private void invokeAwareMethods(final String beanName, final Object bean) {
14 if (bean instanceof Aware) {
15 //.....
16 //实现了 BeanFactoryAware 接口,因此执行 setBeanFactory.
17 //bean==AnnotationAwareAspectJAutoProxyCreator
18 if (bean instanceof BeanFactoryAware) {
19 ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
20 }
21 }
22 }
23
24
25 //2、applyBeanPostProcessorsBeforeInitialization 实现如下:
26 @Override
27 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
28 throws BeansException {
29
30 Object result = existingBean;
31 //获取所有的后置处理器,执行前置Before 处理器。
32 for (BeanPostProcessor processor : getBeanPostProcessors()) {
33 Object current = processor.postProcessBeforeInitialization(result, beanName);
34 if (current == null) {
35 return result;
36 }
37 result = current;
38 }
39 return result;
40 }
41
42 //3、invokeInitMethods 方法的具体实现
43 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
44 throws Throwable {
45
46 boolean isInitializingBean = (bean instanceof InitializingBean);
47 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
48 if (logger.isTraceEnabled()) {
49 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
50 }
51 if (System.getSecurityManager() != null) {
52 try {
53 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
54 ((InitializingBean) bean).afterPropertiesSet();
55 return null;
56 }, getAccessControlContext());
57 }
58 catch (PrivilegedActionException pae) {
59 throw pae.getException();
60 }
61 }
62 else {
63 ((InitializingBean) bean).afterPropertiesSet();
64 }
65 }
66
67 if (mbd != null && bean.getClass() != NullBean.class) {
68 String initMethodName = mbd.getInitMethodName();
69 if (StringUtils.hasLength(initMethodName) &&
70 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
71 !mbd.isExternallyManagedInitMethod(initMethodName)) {
72 invokeCustomInitMethod(beanName, bean, mbd);
73 }
74 }
75 }
76
77 //4、applyBeanPostProcessorsAfterInitialization 具体实现
78 @Override
79 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
80 throws BeansException {
81
82 Object result = existingBean;
83 for (BeanPostProcessor processor : getBeanPostProcessors()) {
84 Object current = processor.postProcessAfterInitialization(result, beanName);
85 if (current == null) {
86 return result;
87 }
88 result = current;
89 }
90 return result;
91 }

【8】执行 Aware 初始化时,会调用 setBeanFactory 方法,我们追下去会发现调用的是 AbstractAdvisorAutoProxyCreator 的setBeanFactory 方法(就是我们分析 AnnotationAwareAspectJAutoProxyCreator 继承关系时的父类 )。
 

 1 @Override
2 public void setBeanFactory(BeanFactory beanFactory) {
3 //调用父类的 setBeanFactory
4 super.setBeanFactory(beanFactory);
5 if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
6 throw new IllegalArgumentException(
7 "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
8 }
9 //AnnotationAwareAspectJAutoProxyCreator 方法对此进行了重写
10 initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
11 }

【9】进入 initBeanFactory 方法,我们知道此方法已被 AnnotationAwareAspectJAutoProxyCreator  重写:

 1 //位于 AnnotationAwareAspectJAutoProxyCreator 类中
2 @Override
3 protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
4 super.initBeanFactory(beanFactory);
5 if (this.aspectJAdvisorFactory == null) {
6 //创建了放射的通知工厂
7 this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
8 }
9 this.aspectJAdvisorsBuilder =
10 new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
11 }

【10】最终 BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功,将其添加到 beanFactory 中。

 1 for (String ppName : orderedPostProcessorNames) {
2 //实例 pp==AnnotationAwareAspectJAutoProxyCreator
3 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
4 //放入 ordered后置处理器集合
5 orderedPostProcessors.add(pp);
6 if (pp instanceof MergedBeanDefinitionPostProcessor) {
7 internalPostProcessors.add(pp);
8 }
9 }
10 //将处理器按优先级排序
11 sortPostProcessors(orderedPostProcessors, beanFactory);
12 //调用注册方法
13 registerBeanPostProcessors(beanFactory, orderedPostProcessors);
14
15 //上述注册方法的内部代码
16 private static void registerBeanPostProcessors(
17 ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
18 //将后置处理器都添加到bean工厂
19 for (BeanPostProcessor postProcessor : postProcessors) {
20 beanFactory.addBeanPostProcessor(postProcessor);
21 }
22 }

四、后置处理器创建后的操作


【1】以上是创建和注册 AnnotationAwareAspectJAutoProxyCreator 的过程。接下来就是对创建后的流程进行说明:AnnotationAwareAspectJAutoProxyCreator 是继承 InstantiationAwareBeanPostProcessor 的后置处理器:我们在上面说的 IOC 容器初始化时,会调用 refresh 方法:我们进入此方法看下,我们之前分析 registerBeanPostProcessors 方法,接下来分析 finishBeanFactoryInitialization 方法(实例所有剩余的单实例bean)完成 BeanFactory 初始化工作。

 1 @Override
2 public void refresh() throws BeansException, IllegalStateException {
3 synchronized (this.startupShutdownMonitor) {
4 //......
5 // 注册 bean后置处理器 来拦截 bean 的创建。
6 registerBeanPostProcessors(beanFactory);
7 //......
8 // 初始化特定上下文子类中的其他特殊bean。
9 onRefresh();
10 //......
11 // 实例化所有剩余的(非延迟初始化)单例。
12 finishBeanFactoryInitialization(beanFactory);
13 }

【2】遍历获取容器中所有的 Bean ,依次创建对象 getBean(beanName); 流程:getBean -> doGetBean() -> getSingleton(),getBean 方法如下:先从缓存中获取当前 bean,如果能获取到说明 bean 是之前被创建过的,直接使用,否则创建bean;只要是创建好的 bean 都会被缓存起来。

 1 // 先检查单例缓存中是否有已存在手动注册的单例,如果存在说明之前bean已创建
2 Object sharedInstance = getSingleton(beanName);
3 //缓存中不存在 bean 时才创建该单例 bean
4 if (sharedInstance != null && args == null) {
5 //...
6 }else{
7 //创建bean实例。
8 if (mbd.isSingleton()) {
9 sharedInstance = getSingleton(beanName, () -> {
10 try {
11 return createBean(beanName, mbd, args);
12 }
13 catch (BeansException ex) {
14 destroySingleton(beanName);
15 throw ex;
16 }
17 });
18 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
19 }
20 }

【2.1】进入创建 bean 的步骤: createBean 方法,首先会调用 resolveBeforeInstantiation 方法,让 beanPostProcessors后置处理器有机会返回代理对象而不是目标 bean 实例。如果能返回则直接使用,如果不能则调用 doCreateBean 方法来创建实例。

 1 @Override
2 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
3 throws BeanCreationException {
4 /*现获取类的基本信息 例如:
5 Root bean: class [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator];
6 scope=singleton等等*/
7 RootBeanDefinition mbdToUse = mbd;
8 //......
9 //让beanPostProcessors有机会返回代理而不是目标bean实例。
10 Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
11 if (bean != null) {
12 return bean;
13 }
14 //通过此方法,先调用 aware、前置处理器、bean初始化、后置处理器 ,之前有分析过。
15 Object beanInstance = doCreateBean(beanName, mbdToUse, args);
16 }

【BeanPostProcessor 是在 Bean 对象创建完成初始化前后调用的】
【InstantiationAwareBeanPostProcessor 是在创建 bean 实例之前先尝试用后置处理器返回代理对象】
  后置处理器与后置处理器不同,具体什么时候调用,需要根据不同情况而定。

【2.1.1】分析 resolveBeforeInstantiation 方法(让 beanPostProcessors 有机会返回代理对象):我们分析的 AnnotationAwareAspectJAutoProxyCreator 就是 InstantiationAwareBeanPostProcessor 类型的后置处理器。会在任何 bean 创建之前先尝试返回 bean 的代理实例。

 1 @Nullable
2 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
3 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
4 if (bean != null) {
5 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
6 }
7 }
8
9 //上面两个方法的源码展示
10 @Nullable
11 protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
12 //获取所有的后置处理器
13 for (BeanPostProcessor bp : getBeanPostProcessors()) {
14 //如果后置处理器是 InstantiationAwareBeanPostProcessor 类型的处理器则执行 postProcessBeforeInstantiation 方法。
15 //我们分析的 AnnotationAwareAspectJAutoProxyCreator 就是 InstantiationAwareBeanPostProcessor 类型的处理器
16 if (bp instanceof InstantiationAwareBeanPostProcessor) {
17 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
18 //***** 后续分析
19 Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
20 if (result != null) {
21 return result;
22 }
23 }
24 }
25 return null;
26 }

【2.1.1.1】接着分析上述的 postProcessBeforeInstantiation 方法:内容较多,放在中分析。
【2.1.2】分析 doCreateBean 方法,之前有介绍过,我们在看下源码:就是对创建的目标类前后对后置处理器的方法进行初始化。才是真正创建一个 bean 的实例。

 1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
2 throws BeanCreationException {
3 //创建 bean 实例
4 instanceWrapper = createBeanInstance(beanName, mbd, args);
5 //bean 属性赋值
6 populateBean(beanName, mbd, instanceWrapper);
7 //初始化 bean
8 exposedObject = initializeBean(beanName, exposedObject, mbd);
9 }
10
11
12 //初始化方法 initializeBean 的源码
13 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
14 //初始化 aware 接口的类
15 invokeAwareMethods(beanName, bean);
16 //后置处理器 Before 方法初始化
17 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
18 //初始化类
19 invokeInitMethods(beanName, wrappedBean, mbd);
20 //后置处理器 after 方法初始化
21 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
22 //返回创建好的类
23 return wrappedBean;
24 }

五、postProcessBeforeInstantiation 方法分析


【1】每个 bean 创建之前,调用此方法。我们主要观察业务逻辑 MathCalculator 类和切面 LogAspects 类的创建。

 1 //当bean = MathCalculator or LogAspects 我们着重分析此方法,其他的略过
2 @Override
3 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
4 Object cacheKey = getCacheKey(beanClass, beanName);
5
6 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
7 //判断当前 bean 是否在 advisedBeans 中(保存了所有需要增加的 bean:意思就是添加了切面的内容),第一次进行肯定是不包含的所以会跳过
8 if (this.advisedBeans.containsKey(cacheKey)) {
9 return null;
10 }
11 //isInfrastructureClass 判断当前类是否为基础类型的,也就是实现了 Advice、Pointcut、Advisor、AopInfrastructureBean
12 //或者是否为切面注解标注的类 (@Aspect),第一个 MathCalculator = false
13 //shouldSkip 是否需要跳过:内部是获取候选的增强器(也就是切面内的通知方法)
14 //将所有的增强器封装成了 List<Advisor> 集合,增强器的类型是 InstantiationModelAwarePointcutAdvisor
15 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
16 this.advisedBeans.put(cacheKey, Boolean.FALSE);
17 return null;
18 }
19 }
20 // targetSource = null
21 TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
22 if (targetSource != null) {
23 if (StringUtils.hasLength(beanName)) {
24 this.targetSourcedBeans.add(beanName);
25 }
26 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
27 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
28 this.proxyTypes.put(cacheKey, proxy.getClass());
29 return proxy;
30 }
31 //直接返回空,进入我们配置类中,创建 MathCalculator 对象
32 return null;
33 }

【2】上述代码中的 shouldSkip 源码:

 1 @Override
2 protected boolean shouldSkip(Class<?> beanClass, String beanName) {
3 //获取所有的增强器 考虑通过缓存方面名称列表进行优化
4 List<Advisor> candidateAdvisors = findCandidateAdvisors();
5 for (Advisor advisor : candidateAdvisors) {
6 //我们的增强器都是 InstantiationModelAwarePointcutAdvisor 类型的,不是AspectJPointcutAdvisor 所以跳过
7 if (advisor instanceof AspectJPointcutAdvisor &&
8 ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
9 return true;
10 }
11 }
12 //父类直接返回 false
13 return super.shouldSkip(beanClass, beanName);
14 }

【3】创建完 MathCalculator 后,调用 postProcessAfterInitialization

 1 @Override
2 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
3 if (bean != null) {
4 // cacheKey = calculator
5 Object cacheKey = getCacheKey(bean.getClass(), beanName);
6 //判断之前是否代理过
7 if (this.earlyProxyReferences.remove(cacheKey) != bean) {
8 //包装目标类,如果需要的话
9 return wrapIfNecessary(bean, beanName, cacheKey);
10 }
11 }
12 return bean;
13 }

【3.1】查看包装方法 wrapIfNecessary 的源码:分析后得出如下结论:以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程

 1 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
2 //...... 省略的都是判断是否为切面类或以代理类
3 //如果需要就创建代理类
4 //getAdvicesAndAdvisorsForBean 获取能在当前类使用的增强器
5 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
6 if (specificInterceptors != DO_NOT_PROXY) {
7 //保存当前 bean 在advisedBeans 表示当前bean 被处理了
8 this.advisedBeans.put(cacheKey, Boolean.TRUE);
9 //创建代理对象 ****重点,返回的是一个通过 Cglib 代理的对象
10 Object proxy = createProxy(
11 bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
12 this.proxyTypes.put(cacheKey, proxy.getClass());
13 return proxy;
14 }
15
16 this.advisedBeans.put(cacheKey, Boolean.FALSE);
17 return bean;

【3.1.1】进入当前类使用的增强器方法:getAdvicesAndAdvisorsForBean

 1 @Override
2 @Nullable
3 protected Object[] getAdvicesAndAdvisorsForBean(
4 Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
5 //获取可用的增强器
6 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
7 if (advisors.isEmpty()) {
8 return DO_NOT_PROXY;
9 }
10 return advisors.toArray();
11 }

【3.1.1.1】进入获取可用增强器的方法:findEligibleAdvisors

 1 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
2 //获取后置增强器
3 List<Advisor> candidateAdvisors = findCandidateAdvisors();
4 //找到能在当前bean中使用的增强器(找那些方法能够切入到当前方法的)
5 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
6 extendAdvisors(eligibleAdvisors);
7 if (!eligibleAdvisors.isEmpty()) {
8 //对增强器进行了排序
9 eligibleAdvisors = sortAdvisors(eligibleAdvisors);
10 }
11 return eligibleAdvisors;
12 }
13
14 //上面获取当前bean中使用的增强器的方法源码
15 protected List<Advisor> findAdvisorsThatCanApply(
16 List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
17
18 ProxyCreationContext.setCurrentProxiedBeanName(beanName);
19 try {
20 //通过 AopUtils工具类获取所有的通知方法
21 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
22 }
23 finally {
24 ProxyCreationContext.setCurrentProxiedBeanName(null);
25 }
26 }
27
28 //工具类方法源码展示
29 public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
30 if (candidateAdvisors.isEmpty()) {
31 return candidateAdvisors;
32 }
33 List<Advisor> eligibleAdvisors = new ArrayList<>();
34 for (Advisor candidate : candidateAdvisors) {
35 //我们的增强器不是此类型
36 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
37 eligibleAdvisors.add(candidate);
38 }
39 }
40 boolean hasIntroductions = !eligibleAdvisors.isEmpty();
41 for (Advisor candidate : candidateAdvisors) {
42 if (candidate instanceof IntroductionAdvisor) {
43 // already processed
44 continue;
45 }
46 //判断增强器是否可用,我们的都是可用的
47 if (canApply(candidate, clazz, hasIntroductions)) {
48 //将所有可以使用的增强器,加入到可用的增强器集合中
49 eligibleAdvisors.add(candidate);
50 }
51 }
52 return eligibleAdvisors;
53 }
54
55 //判断是否为可用的增强器的方法 canApply源码:
56 public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
57 if (advisor instanceof IntroductionAdvisor) {
58 return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
59 }
60 //查看切面的方法是否都能匹配
61 else if (advisor instanceof PointcutAdvisor) {
62 PointcutAdvisor pca = (PointcutAdvisor) advisor;
63 return canApply(pca.getPointcut(), targetClass, hasIntroductions);
64 }
65 else {
66 // It doesn't have a pointcut so we assume it applies.
67 return true;
68 }
69 }

【3.1.2】进入代理对象的创建方法:createProxy

 1 protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
2 @Nullable Object[] specificInterceptors, TargetSource targetSource) {
3
4 if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
5 AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
6 }
7 //创建代理工厂
8 ProxyFactory proxyFactory = new ProxyFactory();
9 proxyFactory.copyFrom(this);
10
11 if (!proxyFactory.isProxyTargetClass()) {
12 if (shouldProxyTargetClass(beanClass, beanName)) {
13 proxyFactory.setProxyTargetClass(true);
14 }
15 else {
16 evaluateProxyInterfaces(beanClass, proxyFactory);
17 }
18 }
19 //获取所有的增强器,并保存在代理工厂
20 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
21 proxyFactory.addAdvisors(advisors);
22 proxyFactory.setTargetSource(targetSource);
23 customizeProxyFactory(proxyFactory);
24
25 proxyFactory.setFrozen(this.freezeProxy);
26 if (advisorsPreFiltered()) {
27 proxyFactory.setPreFiltered(true);
28 }
29 //使用代理工厂创建对象
30 return proxyFactory.getProxy(getProxyClassLoader());
31 }

【3.1.2.1】进入代理工厂创建对象的方法 proxyFactory.getProxy 的源码:

 1 public Object getProxy(@Nullable ClassLoader classLoader) {
2 return createAopProxy().getProxy(classLoader);
3 }
4
5 //进入 createAopProxy().getProxy 内部的内部方法
6 @Override
7 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
8 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
9 Class<?> targetClass = config.getTargetClass();
10 if (targetClass == null) {
11 throw new AopConfigException("TargetSource cannot determine target class: " +
12 "Either an interface or a target is required for proxy creation.");
13 }
14 //创建 JDK 代理或者 Cglib 代理。如果实现了接口则使用 JDK 代理,否则Cglib 代理
15 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
16 return new JdkDynamicAopProxy(config);
17 }
18 return new ObjenesisCglibAopProxy(config);
19 }
20 else {
21 return new JdkDynamicAopProxy(config);
22 }
23 }

六、目标方法执行


【1】容器中保存了组件的代理对象(cglib 增强后的对象),这个对象里面保存了详细信息(比如:增强器,目标对象......)
 

【2】CglibAopProxy.intercept(); 拦截目标方法执行如下:主要是根据 ProxyFactory 对象获取将要执行的目标方法的拦截器链。
   1)、如果没有拦截器链,直接执行目标方法。
   2)、如果有拦截器链,吧需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); 方法。

 1 @Override
2 @Nullable
3 public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
4 Object oldProxy = null;
5 boolean setProxyContext = false;
6 Object target = null;
7 TargetSource targetSource = this.advised.getTargetSource();
8 try {
9 if (this.advised.exposeProxy) {
10 oldProxy = AopContext.setCurrentProxy(proxy);
11 setProxyContext = true;
12 }
13 target = targetSource.getTarget();
14 Class<?> targetClass = (target != null ? target.getClass() : null);
15 //根据 ProxyFactory 对象获取将要执行的目标方法的拦截器链
16 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
17 Object retVal;
18 //如果没有拦截器链,直接执行目标方法。
19 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
20 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
21 retVal = methodProxy.invoke(target, argsToUse);
22 }
23 //如果有拦截器链,吧需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用如下方法。
24 else {
25 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
26 }
27 retVal = processReturnType(proxy, target, method, retVal);
28 return retVal;
29 }
30 finally {
31 //......
32 }
33 }

【3】 拦截器链:List<Object> chain = advised.getInterceptorsAndDynamicInterceptionAdvice 的源码展示:
   1)、List<Object> interceptorList 中保存了所有拦截器,总计5个。一个默认的 ExposeInvocationInterceptor 和 4个增强器。
   2)、遍历所有的增强器,将其转为 Interceptor(拦截器):registry.getInterceptors(advisor);

 1 @Override
2 public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
3 Advised config, Method method, @Nullable Class<?> targetClass) {
4
5 //......
6 //获取所有的增强器进行遍历
7 for (Advisor advisor : advisors) {
8 //判断是否为切面的增强器
9 if (advisor instanceof PointcutAdvisor) {
10 //......
11 //将增强器转化为 MethodInterceptor
12 MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
13 if (mm.isRuntime()) {
14 for (MethodInterceptor interceptor : interceptors) {
15 interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
16 }
17 }
18 else {
19 interceptorList.addAll(Arrays.asList(interceptors));
20 }
21 }
22 else if (advisor instanceof IntroductionAdvisor) {
23 IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
24 if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
25 Interceptor[] interceptors = registry.getInterceptors(advisor);
26 interceptorList.addAll(Arrays.asList(interceptors));
27 }
28 }
29 else {
30 Interceptor[] interceptors = registry.getInterceptors(advisor);
31 interceptorList.addAll(Arrays.asList(interceptors));
32 }
33 }
34
35 return interceptorList;
36 }

3)、将增强器转为 MethodInterceptor,转化方式如下:最终返回拦截器链(每一个通知方法又被包装为方法拦截器,后期都是利用 MethodInterceptor 机制)。

 1 @Override
2 public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
3 List<MethodInterceptor> interceptors = new ArrayList<>(3);
4 Advice advice = advisor.getAdvice();
5 //如果是 MethodInterceptor 直接加入到 list 中
6 if (advice instanceof MethodInterceptor) {
7 interceptors.add((MethodInterceptor) advice);
8 }
9 //如果不是则,使用 AdvisorAdapter 将增强器转为 MethodInterceptor
10 for (AdvisorAdapter adapter : this.adapters) {
11 if (adapter.supportsAdvice(advice)) {
12 interceptors.add(adapter.getInterceptor(advisor));
13 }
14 }
15 if (interceptors.isEmpty()) {
16 throw new UnknownAdviceTypeException(advisor.getAdvice());
17 }
18 return interceptors.toArray(new MethodInterceptor[0]);
19 }

【4】、拦截器链有了之后,创建 CglibMethodInvocation 并执行 proceed 方法:

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

七、拦截器链的触发过程


【1】拦截器链展示:除了默认的方法 ExposeInvocationInterceptor 剩下的 4个都是我们切面中的方法。

【2】如果没有拦截器执行目标方法执行代理对象 CglibMethodInvocation 的 proceed 方法:

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

【3】进入 proceed 方法:

 1 @Override
2 @Nullable
3 public Object proceed() throws Throwable {
4 //判断连接器栏的长度是否 == 0,此方法会在拦截器链的最后一个链时调用
5 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
6 //执行目标方式,输入为:MathCalculator...div...
7 return invokeJoinpoint();
8 }
9 //获取下标=0的拦截器 ExposeInvocationInterceptor
10 Object interceptorOrInterceptionAdvice =
11 this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
12 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
13 //下标0 跳过......
14 }
15 else {
16 // this=ReflectiveMethodInvocation
17 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
18 }
19 }

【4】进入 (MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 方法:会循环调用 list 中的拦截器,直到后置处理器:AspectJMethodBeforeAdvice

 1 //ThreadLocal 线程共享数据 (共享 MethodInvocation)
2 private static final ThreadLocal<MethodInvocation> invocation =
3 new NamedThreadLocal<>("Current AOP method invocation");
4
5 @Override
6 public Object invoke(MethodInvocation mi) throws Throwable {
7 //获取 invocation
8 MethodInvocation oldInvocation = invocation.get();
9 //将当前方法,放入 invocation
10 invocation.set(mi);
11 try {
12 //执行 cglib 的proceed() 就获取到了下标为1的拦截器 AspectJAfterThrowingAdvice
13 return mi.proceed();
14 }
15 finally {
16 //执行后置通知
17 invocation.set(oldInvocation);
18 }
19 }

【5】 当advice = AspectJMethodBeforeAdvice 后置处理器时,invoke 方法如下:

1 @Override
2 public Object invoke(MethodInvocation mi) throws Throwable {
3 //执行后置处理器的 before 方法
4 //输出如下:div运行。。。@Before:参数列表是:{[2, 3]}
5 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
6 //进入上述展示的 processd 方法,此时进入第一个判断语句,执行目标方法
7 return mi.proceed();
8 }

【7】 后置处理器的 After 方法执行的 invoke 方法展示:最终执行结果的返回方法。

 1 @Override
2 public Object invoke(MethodInvocation mi) throws Throwable {
3 try {
4 return mi.proceed();
5 }
6 finally {
7 //执行 after 方法:div结束。。。@After
8 invokeAdviceMethod(getJoinPointMatch(), null, null);
9 }
10 }

【8】上述分析的流程图如下:根据链表循环向下执行,当最后一个后置处理器的 before 执行完成后,进行目标方法,并进行回流执行拦截器的目标方法。

Spring AOP——源码分析的更多相关文章

  1. spring AOP源码分析(三)

    在上一篇文章 spring AOP源码分析(二)中,我们已经知道如何生成一个代理对象了,那么当代理对象调用代理方法时,增强行为也就是拦截器是如何发挥作用的呢?接下来我们将介绍JDK动态代理和cglib ...

  2. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  3. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  4. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  5. Spring AOP 源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

  6. Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

    AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...

  7. 5.2 Spring5源码--Spring AOP源码分析二

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  8. 5.2 spring5源码--spring AOP源码分析二--切面的配置方式

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  9. spring aop 源码分析(三) @Scope注解创建代理对象

    一.源码环境的搭建: @Component @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedP ...

  10. 最简 Spring AOP 源码分析!

    前言 最近在研究 Spring 源码,Spring 最核心的功能就是 IOC 容器和 AOP.本文定位是以最简的方式,分析 Spring AOP 源码. 基本概念 上面的思维导图能够概括了 Sprin ...

随机推荐

  1. 初探AOP

    1.背景介绍 1.什么是AOP 1)在OOP(面向对象编程)中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加.  2)AOP则将封装好的对象剖开,找出其中对多个 ...

  2. python机器学习——朴素贝叶斯算法

    背景与原理: 朴素贝叶斯算法是机器学习领域最经典的算法之一,仍然是用来解决分类问题的. 那么对于分类问题,我们的模型始终是:用$m$组数据,每条数据形如$(x_{1},...,x_{n},y)$,表示 ...

  3. Apple Sources

    1. libsystem_malloc.dylib的源码 https://opensource.apple.com/tarballs/libmalloc/ .这里有多个版本(例如用otool找到iOS ...

  4. 元素定位xpath路径中添加参数的方法

    在某次自动化测试中,需要定位下拉列表(非select列表)中不同的元素,我想到了利用参入参数的方式来实现,经过多次尝试,得到如下方法,与大家分享 例如在通过text定位某个元素时,self.find_ ...

  5. php后端遇到的问题

    1.用文件记录日志,会有并发问题

  6. redis字段使用说明

    Set(集合)增删改查: #删除当前选择数据库中的所有key127.0.0.1:6379> flushdbOK#生成set集合,添加4个数据127.0.0.1:6379> sadd set ...

  7. 开始 go

    为什么开始想转 go ? 毕业三年多,一直从事的是 Java , 大学学的也是 Java ,本来想一直干下去的,可是似乎 Java 水涨船高,面试要求也越来越高. 曾经一起毕业的同事自学 go ,已经 ...

  8. Delphi书籍大全【阿里云盘】

    「marco cantu的Object Pascal Handbook」等文件 https://www.aliyundrive.com/s/sJtUo8ziUpV 提取码: 5tp6点击链接保存,或者 ...

  9. Markdown基础学习

    Markdown学习 一级标题 #加空格 标题二 二级标题 ##加空格 如此类推 标题三 或者Ctrl+123456 字体 加粗 两个** hello world 倾斜一个* hello world ...

  10. javascript原型,继承

    //普通对象 //函数对象(有原型 prototy 的属性) //原型的应用 继承 function Amial(){ this.type = '小于' } function cat(name){ t ...