个人随笔
目录
尝试通过源码弄明白SpringAOP的原理
2021-07-21 22:55:29

在上几篇文章中,我们知道了SpringIOC的大概原理,通过源码把spring从加载配置文件到解析配置文件到实例化过程走了一遍,那这一篇文章我想要尝试下弄明白Spring是怎么实现AOP的?完全通过自己的推测来从源码找答案。

一、AOP例子

要弄明白AOP的实现原理,我们得先看看AOP的功能

1、引入依赖

  1. <!-- aspectJ AOP 织入器 -->
  2. <dependency>
  3. <groupId>org.aspectj</groupId>
  4. <artifactId>aspectjweaver</artifactId>
  5. <version>1.8.9</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-spring-context -->
  8. <dependency>

2、配置类加上注解开启AOP

  1. @Configuration
  2. @ComponentScan(basePackages = "com.suibibk.spring")
  3. @EnableAspectJAutoProxy
  4. public class SpringConfiguration {
  5. //spring容器初始化时,会调用配置类的无参构造函数
  6. public SpringConfiguration(){
  7. System.out.println("容器启动初始化");
  8. }
  9. }

3、业务类

  1. package com.suibibk.spring.service;
  2. public interface UserService {
  3. public void test();
  4. }
  1. package com.suibibk.spring.service;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class UserServiceImpl implements UserService {
  5. public void test() {
  6. System.out.println("就是这么拽");
  7. }
  8. }

4、切面

  1. @Aspect
  2. @Component
  3. public class MyAspect {
  4. @Pointcut("execution(public * com.suibibk.spring.service.*.*(..))")
  5. public void web() {
  6. }
  7. @Around("web()")
  8. public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
  9. System.out.println("之前");
  10. Object obj =pjp.proceed();
  11. System.out.println("之后");
  12. return obj;
  13. }
  14. }

5、启动类

  1. public class App {
  2. public static void main(String[] args) {
  3. ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
  4. UserService userService = (UserService) context.getBean("userServiceImpl");
  5. userService.test();
  6. }
  7. }

6、测试结果

  1. 容器启动初始化
  2. 之前
  3. 就是这么拽
  4. 之后

完美符合预期,在执行业务逻辑前后加上了额外的业务逻辑。

那怎么实现的呢?

二、从什么地方下手?

那我们从什么地方开始阅读源码呢,按我阅读源码的习惯,我是喜欢推测+调试相结合,比如我们前面知道了spring实例化的过程,而AOP肯定是用了动态代理的模式,也就是把正真的bean对象进行了代理包装,也就是肯定是生成了bean对象后包装的,那在实例化后什么地方还会对bean进行增强呢,我们从前面IOC spring 实例化源码知道,有几个地方对这个bean进行包装,这些bean都实现了BeanPostProcessor接口,然后在postProcessBeforeInitialization和postProcessAfterInitialization方法进行处理,我们研究下AOP注解有没有这些,或者有哪一个关键的实现了BeanPostProcessor的类,可以去AOP包下面看看。

1、先看看AOP开启注解有没有什么特殊

  1. @EnableAspectJAutoProxy
  2. public class SpringConfiguration {
  3. //spring容器初始化时,会调用配置类的无参构造函数
  4. public SpringConfiguration(){
  5. System.out.println("容器启动初始化");
  6. }
  7. }

进入@EnableAspectJAutoProxy 看看,记住我们的目标是根据上面的推测找到某些与AOP有关的实现了BeanPostProcessor接口的类,继续点进去看看。

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(AspectJAutoProxyRegistrar.class)
  5. public @interface EnableAspectJAutoProxy

我们看到了@Import注解,这个注解效果跟@Bean@Component的最终效果一样,都是生成一个bean,这里生成的是

  1. AspectJAutoProxyRegistrar.class

这个我们是在上几篇文章中的源码里看过的:https://www.suibibk.com/topic/866818869614870528 ,如下

  1. @Nullable
  2. protected final SourceClass doProcessConfigurationClass(
  3. ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
  4. throws IOException {
  5. if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
  6. // Recursively process any member (nested) classes first
  7. processMemberClasses(configClass, sourceClass, filter);
  8. }
  9. // Process any @PropertySource annotations
  10. for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
  11. sourceClass.getMetadata(), PropertySources.class,
  12. org.springframework.context.annotation.PropertySource.class)) {
  13. if (this.environment instanceof ConfigurableEnvironment) {
  14. processPropertySource(propertySource);
  15. }
  16. else {
  17. logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
  18. "]. Reason: Environment must implement ConfigurableEnvironment");
  19. }
  20. }
  21. // Process any @ComponentScan annotations
  22. Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
  23. sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
  24. if (!componentScans.isEmpty() &&
  25. !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
  26. for (AnnotationAttributes componentScan : componentScans) {
  27. // The config class is annotated with @ComponentScan -> perform the scan immediately
  28. Set<BeanDefinitionHolder> scannedBeanDefinitions =
  29. this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
  30. // Check the set of scanned definitions for any further config classes and parse recursively if needed
  31. for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
  32. BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
  33. if (bdCand == null) {
  34. bdCand = holder.getBeanDefinition();
  35. }
  36. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
  37. parse(bdCand.getBeanClassName(), holder.getBeanName());
  38. }
  39. }
  40. }
  41. }
  42. // Process any @Import annotations
  43. processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
  44. // Process any @ImportResource annotations
  45. AnnotationAttributes importResource =
  46. AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
  47. if (importResource != null) {
  48. String[] resources = importResource.getStringArray("locations");
  49. Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
  50. for (String resource : resources) {
  51. String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
  52. configClass.addImportedResource(resolvedResource, readerClass);
  53. }
  54. }
  55. // Process individual @Bean methods
  56. Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
  57. for (MethodMetadata methodMetadata : beanMethods) {
  58. configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
  59. }
  60. // Process default methods on interfaces
  61. processInterfaces(configClass, sourceClass);
  62. // Process superclass, if any
  63. if (sourceClass.getMetadata().hasSuperClass()) {
  64. String superclass = sourceClass.getMetadata().getSuperClassName();
  65. if (superclass != null && !superclass.startsWith("java") &&
  66. !this.knownSuperclasses.containsKey(superclass)) {
  67. this.knownSuperclasses.put(superclass, configClass);
  68. // Superclass found, return its annotation metadata and recurse
  69. return sourceClass.getSuperClass();
  70. }
  71. }
  72. // No superclass -> processing is complete
  73. return null;
  74. }

我们那时候只关注了@ComponentScan ,其实可以看到后面有Process any @Import annotations ,所以这里推测效果一样,我们继续点进去,看看它实例化的bean是啥

  1. /**
  2. * Registers an {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
  3. * AnnotationAwareAspectJAutoProxyCreator} against the current {@link BeanDefinitionRegistry}
  4. * as appropriate based on a given @{@link EnableAspectJAutoProxy} annotation.
  5. *
  6. * @author Chris Beams
  7. * @author Juergen Hoeller
  8. * @since 3.1
  9. * @see EnableAspectJAutoProxy
  10. */
  11. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  12. /**
  13. * Register, escalate, and configure the AspectJ auto proxy creator based on the value
  14. * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
  15. * {@code @Configuration} class.
  16. */
  17. @Override
  18. public void registerBeanDefinitions(
  19. AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  20. AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
  21. AnnotationAttributes enableAspectJAutoProxy =
  22. AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
  23. if (enableAspectJAutoProxy != null) {
  24. if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
  25. AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
  26. }
  27. if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
  28. AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
  29. }
  30. }
  31. }
  32. }

到这里有点懵,就这?那registerBeanDefinitions方法什么时候调用的呢?此时我们可以在这里打个断点,看看这个方法什么时候调用的。通过断点调试,然后跳出这个方法我们发现回到了熟悉的解析配置类那里

  1. do {
  2. parser.parse(candidates);
  3. parser.validate();
  4. Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
  5. configClasses.removeAll(alreadyParsed);
  6. // Read the model and create bean definitions based on its content
  7. if (this.reader == null) {
  8. this.reader = new ConfigurationClassBeanDefinitionReader(
  9. registry, this.sourceExtractor, this.resourceLoader, this.environment,
  10. this.importBeanNameGenerator, parser.getImportRegistry());
  11. }
  12. this.reader.loadBeanDefinitions(configClasses);
  13. alreadyParsed.addAll(configClasses);
  14. ...
  1. this.reader.loadBeanDefinitions(configClasses);

在这里做了调用,也就是解析完配置类就做了这个调用了,这里我们不去了解具体怎么调用先,我们的目的不在这,我们只要知道spring在这个地方进行了合理的调用就好了。

然后我们回到上面看第一行代码

  1. AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

貌似注册了个啥,到registry中,我们知道registry就是DefaultListableBeanFactory,这里可以推测应该是注册了一个什么类到DefaultListableBeanFactory中的beanDefinitionMap中,key为bean的名称,值为beanDefinition放的应该是这些后置处理器的相关类定义,这里可以直接推测是后置处理器,也就是实现了BeanPostProcessor接口的类,毕竟不实现这个接口的话,在实例化完执行

  1. exposedObject = initializeBean(beanName, exposedObject, mbd);

里面的

  1. if (mbd == null || !mbd.isSynthetic()) {
  2. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  3. }

  1. if (mbd == null || !mbd.isSynthetic()) {
  2. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  3. }

将不能对所有的目标bean进行增强。
我们点进去看看

  1. @Nullable
  2. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
  3. return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
  4. }
  1. @Nullable
  2. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  3. BeanDefinitionRegistry registry, @Nullable Object source) {
  4. return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
  5. }
  1. @Nullable
  2. private static BeanDefinition registerOrEscalateApcAsRequired(
  3. Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
  4. Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
  5. if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
  6. BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
  7. if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
  8. int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
  9. int requiredPriority = findPriorityForClass(cls);
  10. if (currentPriority < requiredPriority) {
  11. apcDefinition.setBeanClassName(cls.getName());
  12. }
  13. }
  14. return null;
  15. }
  16. RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
  17. beanDefinition.setSource(source);
  18. beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
  19. beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  20. registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
  21. return beanDefinition;
  22. }

不出意料这里果然有熟悉的代码

  1. RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
  2. beanDefinition.setSource(source);
  3. beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
  4. beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  5. registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
  6. return beanDefinition;

那这个cls是关键,cls是上面传进来的AnnotationAwareAspectJAutoProxyCreator.class。我们看看这个类的继承关系,看看是否是我们的目标类。

  1. public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator
  2. public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator
  3. public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator
  4. public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
  5. public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
  6. public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
  7. public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
  8. public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor

我去,这也太复杂了,不过好歹看到了我们的目标BeanPostProcessor,我们看看那个类有我们的这两个方法

  1. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
  2. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException

最终我们在AbstractAutoProxyCreator.class中找到了目标

  1. @Override
  2. public Object postProcessBeforeInitialization(Object bean, String beanName) {
  3. return bean;
  4. }
  5. ...
  6. /**
  7. * Create a proxy with the configured interceptors if the bean is
  8. * identified as one to proxy by the subclass.
  9. * @see #getAdvicesAndAdvisorsForBean
  10. */
  11. @Override
  12. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  13. if (bean != null) {
  14. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  15. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  16. return wrapIfNecessary(bean, beanName, cacheKey);
  17. }
  18. }
  19. return bean;
  20. }

postProcessBeforeInitialization方法只是简单的返回了bean,关键点在postProcessAfterInitialization方法,也是肯定要在最后进行包装才对,我们为了确认是不是在

  1. if (mbd == null || !mbd.isSynthetic()) {
  2. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  3. }

这里调用的,可以打个断点试试,经过测试,就是从这里进去执行的,所以我们接下来只需要分析

  1. /**
  2. * Create a proxy with the configured interceptors if the bean is
  3. * identified as one to proxy by the subclass.
  4. * @see #getAdvicesAndAdvisorsForBean
  5. */
  6. @Override
  7. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  8. if (bean != null) {
  9. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  10. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  11. return wrapIfNecessary(bean, beanName, cacheKey);
  12. }
  13. }
  14. return bean;
  15. }

来看看spring怎么搞得,怎么把我们的切面给包装进去。

三、怎么生成代理对象的?

我们从上面可以知道,在bean实例化后会调用

  1. exposedObject = initializeBean(beanName, exposedObject, mbd);

来进行初始化,里面会调用

if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

  1. 来执行一系列的BeanPostProcessorsapplyBeanPostProcessorsAfterInitialization方法,而我们的AOP通过@EnableAspectJAutoProxy注解会注入一个bean:AspectJAutoProxyRegistrar.classspring解析配置类后会调用这个对象的public void registerBeanDefinitions(xxx)方法把一个AnnotationAwareAspectJAutoProxyCreator放入DefaultListableBeanFactory中的beanDefinitionMap中,keybean的名称,值为beanDefinition放的是这个类的相关类定义,这个类实现了BeanPostProcessor接口。所以关键代码就是这个类的applyBeanPostProcessorsAfterInitialization方法的逻辑,看看是如何对bean进行包装的。

/**

  • Create a proxy with the configured interceptors if the bean is:如果bean是,则使用已配置的拦截器创建代理
  • identified as one to proxy by the subclass.
  • @see #getAdvicesAndAdvisorsForBean
    */
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
    1. Object cacheKey = getCacheKey(bean.getClass(), beanName);
    2. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    3. return wrapIfNecessary(bean, beanName, cacheKey);
    4. }
    }
    return bean;
    }
    ```
    我们看wrapIfNecessary方法
  1. /**
  2. * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.:如果需要,包装给定的bean,也就是说,如果它符合被代理的条件。
  3. * @param bean the raw bean instance
  4. * @param beanName the name of the bean
  5. * @param cacheKey the cache key for metadata access
  6. * @return a proxy wrapping the bean, or the raw bean instance as-is
  7. */
  8. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  9. if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
  10. return bean;
  11. }
  12. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  13. return bean;
  14. }
  15. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  16. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  17. return bean;
  18. }
  19. // Create proxy if we have advice.
  20. //1、如果我们有通知,则创建代理,而获Advice里面就会根据我们的MyAspect的相关规则来筛选了,这里不详细去研究了,反正我们的目的只是找主脉络
  21. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  22. if (specificInterceptors != DO_NOT_PROXY) {
  23. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  24. Object proxy = createProxy(
  25. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  26. this.proxyTypes.put(cacheKey, proxy.getClass());
  27. return proxy;
  28. }
  29. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  30. return bean;
  31. }

我们调试,发现specificInterceptors的内容如下:

  1. [org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR, InstantiationModelAwarePointcutAdvisor: expression [web()]; advice method [public java.lang.Object com.suibibk.spring.MyAspect.doAround(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; perClauseKind=SINGLETON]

包括我们的

  1. com.suibibk.spring.MyAspect.doAround(org.aspectj.lang.ProceedingJoinPoint)

然后接下来就是去创建代理了,我们点进去看下

  1. /**
  2. * Create an AOP proxy for the given bean.
  3. * @param beanClass the class of the bean
  4. * @param beanName the name of the bean
  5. * @param specificInterceptors the set of interceptors that is
  6. * specific to this bean (may be empty, but not null)
  7. * @param targetSource the TargetSource for the proxy,
  8. * already pre-configured to access the bean
  9. * @return the AOP proxy for the bean
  10. * @see #buildAdvisors
  11. */
  12. protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
  13. @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  14. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
  15. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  16. }
  17. ProxyFactory proxyFactory = new ProxyFactory();
  18. proxyFactory.copyFrom(this);
  19. if (!proxyFactory.isProxyTargetClass()) {
  20. if (shouldProxyTargetClass(beanClass, beanName)) {
  21. proxyFactory.setProxyTargetClass(true);
  22. }
  23. else {
  24. evaluateProxyInterfaces(beanClass, proxyFactory);
  25. }
  26. }
  27. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  28. proxyFactory.addAdvisors(advisors);
  29. proxyFactory.setTargetSource(targetSource);
  30. customizeProxyFactory(proxyFactory);
  31. proxyFactory.setFrozen(this.freezeProxy);
  32. if (advisorsPreFiltered()) {
  33. proxyFactory.setPreFiltered(true);
  34. }
  35. return proxyFactory.getProxy(getProxyClassLoader());
  36. }

这个按字面意思直接看最后

  1. /**
  2. * Create a new proxy according to the settings in this factory.
  3. * <p>Can be called repeatedly. Effect will vary if we've added
  4. * or removed interfaces. Can add and remove interceptors.
  5. * <p>Uses the given class loader (if necessary for proxy creation).
  6. * @param classLoader the class loader to create the proxy with
  7. * (or {@code null} for the low-level proxy facility's default)
  8. * @return the proxy object
  9. */
  10. public Object getProxy(@Nullable ClassLoader classLoader) {
  11. return createAopProxy().getProxy(classLoader);
  12. }

我们来看看createAopProxy()方法,看看是用什么来创建代理,我们知道创建动态代理无非就两样,一个是JDK自带的,一个是CGLIB,如果被代理的类有实现接口,通常永辉jdk自带的,否则会用cglib,我们点进去看看。

  1. /**
  2. * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
  3. * create an AOP proxy with {@code this} as an argument.
  4. */
  5. protected final synchronized AopProxy createAopProxy() {
  6. if (!this.active) {
  7. activate();
  8. }
  9. return getAopProxyFactory().createAopProxy(this);
  10. }
  1. @Override
  2. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
  3. if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
  4. Class<?> targetClass = config.getTargetClass();
  5. if (targetClass == null) {
  6. throw new AopConfigException("TargetSource cannot determine target class: " +
  7. "Either an interface or a target is required for proxy creation.");
  8. }
  9. if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
  10. return new JdkDynamicAopProxy(config);
  11. }
  12. return new ObjenesisCglibAopProxy(config);
  13. }
  14. else {
  15. return new JdkDynamicAopProxy(config);
  16. }
  17. }

对头,如果目标类是接口,则用JdkDynamicAopProxy,否则用ObjenesisCglibAopProxy,跟预想中的一样。

如果是jdk

  1. @Override
  2. public Object getProxy(@Nullable ClassLoader classLoader) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
  5. }
  6. Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  7. findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  8. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  9. }

如果是cglib

  1. @Override
  2. public Object getProxy(@Nullable ClassLoader classLoader) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
  5. }
  6. try {
  7. Class<?> rootClass = this.advised.getTargetClass();
  8. Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
  9. Class<?> proxySuperClass = rootClass;
  10. if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
  11. proxySuperClass = rootClass.getSuperclass();
  12. Class<?>[] additionalInterfaces = rootClass.getInterfaces();
  13. for (Class<?> additionalInterface : additionalInterfaces) {
  14. this.advised.addInterface(additionalInterface);
  15. }
  16. }
  17. // Validate the class, writing log messages as necessary.
  18. validateClassIfNecessary(proxySuperClass, classLoader);
  19. // Configure CGLIB Enhancer...
  20. Enhancer enhancer = createEnhancer();
  21. if (classLoader != null) {
  22. enhancer.setClassLoader(classLoader);
  23. if (classLoader instanceof SmartClassLoader &&
  24. ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
  25. enhancer.setUseCache(false);
  26. }
  27. }
  28. enhancer.setSuperclass(proxySuperClass);
  29. enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
  30. enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
  31. enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
  32. Callback[] callbacks = getCallbacks(rootClass);
  33. Class<?>[] types = new Class<?>[callbacks.length];
  34. for (int x = 0; x < types.length; x++) {
  35. types[x] = callbacks[x].getClass();
  36. }
  37. // fixedInterceptorMap only populated at this point, after getCallbacks call above
  38. enhancer.setCallbackFilter(new ProxyCallbackFilter(
  39. this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
  40. enhancer.setCallbackTypes(types);
  41. // Generate the proxy class and create a proxy instance.
  42. return createProxyClassAndInstance(enhancer, callbacks);
  43. }
  44. catch (CodeGenerationException | IllegalArgumentException ex) {
  45. throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
  46. ": Common causes of this problem include using a final class or a non-visible class",
  47. ex);
  48. }
  49. catch (Throwable ex) {
  50. // TargetSource.getTarget() failed
  51. throw new AopConfigException("Unexpected AOP exception", ex);
  52. }
  53. }

到这里其实大概已经知道了AOP的实现原理,其它都是细节研究,比如怎么活动Advice啊。

一句话总结:Spring就是靠各种特殊的BeanPostProcessor来在实例化bean后对bean进行增强的。

一个简单的例子来探寻Spring实例化bean执行源码的主脉络(一):this()方法
一个简单的例子来探寻Spring实例化bean执行源码的主脉络(二):解析配置类
一个简单的例子来探寻Spring实例化bean执行源码的主脉络(三):扫包和实例化

 12

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号