静态AOP-Spring集成AspectJ

一、XML配置静态AOP load-time-weaver

1、BeanDefinition解析阶段自定义名称空间 load-time-weaver

1.1 注册LoadTimeWeaverBeanDefinitionParser

public class ContextNamespaceHandler extends NamespaceHandlerSupport {

@Override

public void init() {

 registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());

 registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());

 registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());

 registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());

 registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());

 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());

 registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());

 registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());

}

}

 

1.2 load-time-weaver标签注册为名称为loadTimeWeaver的Bean LoadTimeWeaverBeanDefinitionParser

 private static final String DEFAULT_LOAD_TIME_WEAVER_CLASS_NAME =

  "org.springframework.context.weaving.DefaultContextLoadTimeWeaver";

 

protected String getBeanClassName(Element element) {

 if (element.hasAttribute(WEAVER_CLASS_ATTRIBUTE)) {

  return element.getAttribute(WEAVER_CLASS_ATTRIBUTE);

 }

 return DEFAULT_LOAD_TIME_WEAVER_CLASS_NAME;

}

 

protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {

 // String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";

 return ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME;

}

 

private static final String ASPECTJ_WEAVING_ATTRIBUTE = "aspectj-weaving";

 

public static final String ASPECTJ_WEAVING_ENABLER_BEAN_NAME =

  "org.springframework.context.config.internalAspectJWeavingEnabler";

 

private static final String ASPECTJ_WEAVING_ENABLER_CLASS_NAME =

  "org.springframework.context.weaving.AspectJWeavingEnabler";

 

protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {

 builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

 

 // 

 if (isAspectJWeavingEnabled(element.getAttribute(ASPECTJ_WEAVING_ATTRIBUTE), parserContext)) {

  if (!parserContext.getRegistry().containsBeanDefinition(ASPECTJ_WEAVING_ENABLER_BEAN_NAME)) {

   RootBeanDefinition def = new RootBeanDefinition(ASPECTJ_WEAVING_ENABLER_CLASS_NAME);

   parserContext.registerBeanComponent(

     new BeanComponentDefinition(def, ASPECTJ_WEAVING_ENABLER_BEAN_NAME));

  }

 

  // 存在AnnotationBeanConfigurerAspect时注册为Bean

  if (isBeanConfigurerAspectEnabled(parserContext.getReaderContext().getBeanClassLoader())) {

   new SpringConfiguredBeanDefinitionParser().parse(element, parserContext);

  }

 }

}

 

// 是否开启AspectJ静态织入

protected boolean isAspectJWeavingEnabled(String value, ParserContext parserContext) {

 if ("on".equals(value)) {

  return true;

 }

 else if ("off".equals(value)) {

  return false;

 }

 else {

  // Determine default...

  ClassLoader cl = parserContext.getReaderContext().getBeanClassLoader();

 // String ASPECTJ_AOP_XML_RESOURCE = "META-INF/aop.xml";

  return (cl != null && cl.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) != null);

 }

}

 

// 是否存在AnnotationBeanConfigurerAspect

protected boolean isBeanConfigurerAspectEnabled(@Nullable ClassLoader beanClassLoader) {

// String BEAN_CONFIGURER_ASPECT_CLASS_NAME =

"org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect";

 return ClassUtils.isPresent(SpringConfiguredBeanDefinitionParser.BEAN_CONFIGURER_ASPECT_CLASS_NAME,

   beanClassLoader);

}

 

1.3 注册AnnotationBeanConfigurerAspect-SpringConfiguredBeanDefinitionParser

class SpringConfiguredBeanDefinitionParser implements BeanDefinitionParser {

public static final String BEAN_CONFIGURER_ASPECT_BEAN_NAME =

  "org.springframework.context.config.internalBeanConfigurerAspect";

 

static final String BEAN_CONFIGURER_ASPECT_CLASS_NAME =

  "org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect";

 

// 注册AnnotationBeanConfigurerAspect,能够获取ApsectJ织入增强后的对象

public BeanDefinition parse(Element element, ParserContext parserContext) {

 if (!parserContext.getRegistry().containsBeanDefinition(BEAN_CONFIGURER_ASPECT_BEAN_NAME)) {

  RootBeanDefinition def = new RootBeanDefinition();

  def.setBeanClassName(BEAN_CONFIGURER_ASPECT_CLASS_NAME);

  def.setFactoryMethodName("aspectOf");

  def.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

  def.setSource(parserContext.extractSource(element));

  parserContext.registerBeanComponent(new BeanComponentDefinition(def, BEAN_CONFIGURER_ASPECT_BEAN_NAME));

 }

 return null;

}

}

 

2、LoadTimeWeaverAwareProcessor

2.1 注册LoadTimeWeaverAwareProcessor

AbstractApplicationContext.prepareBeanFactory

// String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";

if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {

  beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));

  // Set a temporary ClassLoader for type matching.

  beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));

 }

 

2.2 Bean初始化前注入LoadTimeWeaver

LoadTimeWeaverAwareProcessor实现了BeanPostProcessor。

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

 if (bean instanceof LoadTimeWeaverAware) {

  LoadTimeWeaver ltw = this.loadTimeWeaver;

  if (ltw == null) {

   Assert.state(this.beanFactory != null,

     "BeanFactory required if no LoadTimeWeaver explicitly specified");

   ltw = this.beanFactory.getBean(

     ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME, LoadTimeWeaver.class);

  }

  ((LoadTimeWeaverAware) bean).setLoadTimeWeaver(ltw);

 }

 return bean;

}

 

3、AspectJWeavingEnabler

invokeBeanFactoryPostProcessors()执行BeanFactory后处理器,AspectJWeavingEnabler实现了BeanFactoryPostProcessor。

在执行postProcessBeanFactory时,作为bean的AspectJWeavingEnabler已经实例化,已经注入loadTimeWeaver为DefaultContextLoadTimeWeaver,由LoadTimeWeaverAwareProcessor注入的。        

DefaultContextLoadTimeWeaver中会根据不同的应用环境(Tomcat、GlassFish、JBoss、WebSphere、WebLogic)创建相应的LoadTimeWeaver,因为不同的应用容器都实现了自己的类加载器,注册transformer的方式各有差异,默认环境中使用的类加载器是sun.misc.Launcher.AppClassLoader,    

DefaultContextLoadTimeWeaver包装了实际的LoadTimeWeaver,是装饰器模式的应用,LoadTimeWeaver提供统一的接口屏蔽了不同类加载器注册transformer的差异,实现一致处理。这里实际创建了InstrumentationLoadTimeWeaver,最终调用了Instrumentation.addTransformer(),参数为通过委托模式包装过的AspectJ的ClassPreProcessorAgentAdapter。这就是通过Spring整合AspectJ的过程,至于具体的类加载阶段的处理则由AspectJ接管。

 

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

 enableAspectJWeaving(this.loadTimeWeaver, this.beanClassLoader);

}

 

// 使用给定的{@link LoadTimeWeaver}启用AspectJ编织。

public static void enableAspectJWeaving(

  @Nullable LoadTimeWeaver weaverToUse, @Nullable ClassLoader beanClassLoader) {

 if (weaverToUse == null) {

  if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) {

   weaverToUse = new InstrumentationLoadTimeWeaver(beanClassLoader);

  }

  else {

   throw new IllegalStateException("No LoadTimeWeaver available");

  }

 }

 weaverToUse.addTransformer(

   new AspectJClassBypassingClassFileTransformer(new ClassPreProcessorAgentAdapter()));

}

 

// ClassFileTransformer装饰器,它禁止对AspectJ 类的处理,以避免潜在的LinkageErrors。

private static class AspectJClassBypassingClassFileTransformer implements ClassFileTransformer {

 private final ClassFileTransformer delegate;

 

 public AspectJClassBypassingClassFileTransformer(ClassFileTransformer delegate) {

  this.delegate = delegate;

 }

 

 @Override

 public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,

   ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

 

  if (className.startsWith("org.aspectj") || className.startsWith("org/aspectj")) {

   return classfileBuffer;

  }

  return this.delegate.transform(loader, className, classBeingRedefined, protectionDomain,

classfileBuffer);

 }

}

 

二、注解配置AOP静态代理 EnableLoadTimeWeaving

2.1 LoadTimeWeavingConfiguration

public void setImportMetadata(AnnotationMetadata importMetadata) {

 this.enableLTW = AnnotationConfigUtils.attributesFor(importMetadata, EnableLoadTimeWeaving.class);

 if (this.enableLTW == null) {

  throw new IllegalArgumentException(

    "@EnableLoadTimeWeaving is not present on importing class " + importMetadata.getClassName());

 }

}

 

@Bean(name = ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME)

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

public LoadTimeWeaver loadTimeWeaver() {

 Assert.state(this.beanClassLoader != null, "No ClassLoader set");

 LoadTimeWeaver loadTimeWeaver = null;

 

 if (this.ltwConfigurer != null) {

  // The user has provided a custom LoadTimeWeaver instance

  loadTimeWeaver = this.ltwConfigurer.getLoadTimeWeaver();

 }

 

 if (loadTimeWeaver == null) {

  // No custom LoadTimeWeaver provided -> fall back to the default

  loadTimeWeaver = new DefaultContextLoadTimeWeaver(this.beanClassLoader);

 }

 

 if (this.enableLTW != null) {

  AspectJWeaving aspectJWeaving = this.enableLTW.getEnum("aspectjWeaving");

  switch (aspectJWeaving) {

   case DISABLED:

    // AJ weaving is disabled -> do nothing

    break;

   case AUTODETECT:

    if (this.beanClassLoader.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) == null) {

     // No aop.xml present on the classpath -> treat as 'disabled'

     break;

    }

    // aop.xml is present on the classpath -> enable

    AspectJWeavingEnabler.enableAspectJWeaving(loadTimeWeaver, this.beanClassLoader);

    break;

   case ENABLED:

    AspectJWeavingEnabler.enableAspectJWeaving(loadTimeWeaver, this.beanClassLoader);

    break;

  }

 }

 

 return loadTimeWeaver;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值