Spring源码阅读-注解实现AOP
2017-07-21 00:00
627 查看
写配置文件对很多人来说是一件比较痛苦的事,spring为了使用更方便也支持了用注解实现AOP,看个例子:
执行结果:
before==========
name:zhangsan
after===========
上面配置需要注意的是AspectJTest 对象也要被加载到BeanFactory中才会生效,spring并不会扫描@Aspect注解来创建对象,只会根据该注解创建切面。
虽说用注解可以实现aop,但是注解本身还是需要配置来驱动的,找到aop:aspectj-autoproxy对应的处理类:
跟踪AspectJAutoProxyBeanDefinitionParser的parse方法:
看到这里的逻辑跟前一篇中 configureAutoProxyCreator 注册自动代理创建器逻辑一样,只是默认类变成了AnnotationAwareAspectJAutoProxyCreator,它是AspectJAwareAdvisorAutoProxyCreator的子类。
3ff0
再看extendBeanDefinition(element, parserContext); 这个方法是用来处理aop:aspectj-autoproxy的子标签aop:include的,目的是把include的name属性取出来设置到代理创建器的 includePatterns 属性中,看代码:
这个includePatterns是用来过滤aspect的,如果没有配置则所有被@Aspect修饰的对象都生效,如果配置了,则aspect对象名称必须至少满足一个include name的规则(正则表达式),这些从includePatterns使用的地方就可以知道,如下:
跟前一篇比较用注解实现aop只是入口不一样,最终目的还是把代理创建器以BeanDefinition的形式注册到BeanFactory中,后一篇会看spring是怎么使用这些代理创建器创建代理对象的。
@Aspect public class AspectJTest { @Pointcut(value="execution(* com.myframe.modules.test.service.impl.**.query*(..))") public void pointcut() { } @Before(value="pointcut()") public void before() { System.out.println("before=========="); } @After(value="pointcut()") public void after() { System.err.println("after==========="); } } public class Person implements IPerson { private String name; public String queryName() { System.out.println("name:" + name); return name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
<bean id="person" class="com.myframe.modules.test.service.impl.Person"> <property name="name" value="zhangsan"></property> </bean> <bean class="com.myframe.modules.test.service.impl.AspectJTest"></bean> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
执行结果:
before==========
name:zhangsan
after===========
上面配置需要注意的是AspectJTest 对象也要被加载到BeanFactory中才会生效,spring并不会扫描@Aspect注解来创建对象,只会根据该注解创建切面。
虽说用注解可以实现aop,但是注解本身还是需要配置来驱动的,找到aop:aspectj-autoproxy对应的处理类:
public class AopNamespaceHandler extends NamespaceHandlerSupport { /** * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the ' * {@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}' * and '{@code scoped-proxy}' tags. */ @Override public void init() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); // Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } }
跟踪AspectJAutoProxyBeanDefinitionParser的parse方法:
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); extendBeanDefinition(element, parserContext); return null; } } public abstract class AopNamespaceUtils { //默认自动代理创建器 public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); } } public abstract class AopConfigUtils { public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } }
看到这里的逻辑跟前一篇中 configureAutoProxyCreator 注册自动代理创建器逻辑一样,只是默认类变成了AnnotationAwareAspectJAutoProxyCreator,它是AspectJAwareAdvisorAutoProxyCreator的子类。
3ff0
再看extendBeanDefinition(element, parserContext); 这个方法是用来处理aop:aspectj-autoproxy的子标签aop:include的,目的是把include的name属性取出来设置到代理创建器的 includePatterns 属性中,看代码:
private void extendBeanDefinition(Element element, ParserContext parserContext) { BeanDefinition beanDef = parserContext.getRegistry() .getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME); if (element.hasChildNodes()) { addIncludePatterns(element, parserContext, beanDef); } } private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) { ManagedList<TypedStringValue> includePatterns = new ManagedList<TypedStringValue>(); NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); // 就一个子标签include, 只要判断是不是元素 if (node instanceof Element) { Element includeElement = (Element) node; TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name")); valueHolder.setSource(parserContext.extractSource(includeElement)); includePatterns.add(valueHolder); } } if (!includePatterns.isEmpty()) { includePatterns.setSource(parserContext.extractSource(element)); //把include中的name取出来设置到代理创建器的includePatterns属性中 beanDef.getPropertyValues().add("includePatterns", includePatterns); } }
这个includePatterns是用来过滤aspect的,如果没有配置则所有被@Aspect修饰的对象都生效,如果配置了,则aspect对象名称必须至少满足一个include name的规则(正则表达式),这些从includePatterns使用的地方就可以知道,如下:
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator { /** * Check whether the given aspect bean is eligible for auto-proxying. * <p> * If no <aop:include> elements were used then "includePatterns" will * be {@code null} and all beans are included. If "includePatterns" is * non-null, then one of the patterns must match. */ protected boolean isEligibleAspectBean(String beanName) { if (this.includePatterns == null) { return true; } else { for (Pattern pattern : this.includePatterns) { //正则表达式 if (pattern.matcher(beanName).matches()) { return true; } } return false; } } }
跟前一篇比较用注解实现aop只是入口不一样,最终目的还是把代理创建器以BeanDefinition的形式注册到BeanFactory中,后一篇会看spring是怎么使用这些代理创建器创建代理对象的。
相关文章推荐
- Spring源码阅读-使用ProxyFactoryBean实现AOP
- spring源码剖析(五)利用AOP实现自定义Spring注解
- spring源码剖析(五)利用AOP实现自定义Spring注解
- springboot aop 自定义注解方式实现一套完善的日志记录(完整源码)
- Spring源码阅读-通用配置实现AOP
- 深入剖析Spring Web源码(九) - 处理器映射,处理器适配器以及处理器的实现 - 基于注解控制器流程的实现
- Spring Aop之AspectJ注解配置实现日志管理
- springAop,注解annotation + redis 实现分布式锁
- Spring和Mybatis整合---注解实现AOP事务
- 第五章 Spring进阶-注解方式实现AOP(1)
- 【Spring aop】Spring aop的XML和注解的两种配置实现
- Spring——使用Spring的注解方式实现面向切面技术AOP
- Spring - 注解实现AOP的五种通知
- Spring AOP+注解的方式实现缓存的获取
- 基于注解的spring AOP简单实现
- spring AOP 之 注解 配置实现(附 Java 代码实例)
- Spring动态代理,aop 注解实现aop
- Spring系列之 (十六):利用Spring AOP和自定义注解实现日志功能
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程