文档章节

Spring源码阅读-注解实现AOP

Small-Liu
 Small-Liu
发布于 2017/07/21 17:36
字数 779
阅读 27
收藏 0
点赞 0
评论 0

写配置文件对很多人来说是一件比较痛苦的事,spring为了使用更方便也支持了用注解实现AOP,看个例子:

@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的子类。

 

再看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 &lt;aop:include&gt; 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是怎么使用这些代理创建器创建代理对象的。

© 著作权归作者所有

共有 人打赏支持
Small-Liu
粉丝 15
博文 56
码字总数 49976
作品 0
南京
程序员
Spring AOP 源码分析 - 筛选合适的通知器

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

java高级架构牛人 ⋅ 06/21 ⋅ 0

IOC/AOP工具 - jBeanBox

jBeanBox是一个微形但功能较齐全的IOC/AOP工具适用于JAVA7+,利用了Java的初始化块实现的Java配置代替XML。jBeanBox采用Apache License 2.0开源协议。 其他一些IOC/AOP框架的问题: 1)Sprin...

yong9981 ⋅ 2016/07/25 ⋅ 14

Spring AOP就是这么简单啦

前言 只有光头才能变强 上一篇已经讲解了Spring IOC知识点一网打尽!,这篇主要是讲解Spring的AOP模块~ 之前我已经写过一篇关于AOP的文章了,那篇把比较重要的知识点都讲解过了一篇啦:Sprin...

Java3y ⋅ 05/24 ⋅ 0

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

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

java高级架构牛人 ⋅ 06/21 ⋅ 0

springboot + shiro 权限注解、请求乱码解决、统一异常处理

springboot + shiro 权限注解、请求乱码解决、统一异常处理 前篇 后台权限管理系统 相关: spring boot + mybatis + layui + shiro后台权限管理系统 springboot + shiro之登录人数限制、登录...

wyait ⋅ 06/06 ⋅ 0

Spring之使用注解配置Spring AOP

Spring框架通过注解配置AOP是基于AspectJ实现的。 Spring框架只是直接使用了AspectJ的注解,但并没有使用AspectJ的编译器或织入器,仍然是在运行时动态生成AOP代理。 aspectj使用的是静态代理...

Java攻城玩家 ⋅ 05/31 ⋅ 0

Spring IOC 容器源码分析 - 创建单例 bean 的过程

1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是的实现逻辑。对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去创建,而是从缓存中获取。如果某个 bean...

coolblog ⋅ 06/04 ⋅ 0

Spring IOC 容器源码分析系列文章导读

1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本。经过十几年的迭代,现在的 Spring 框架已经非常成熟了。Spring 包含了众多模块,包括但不限于...

coolblog ⋅ 05/30 ⋅ 0

java利用AOP 实现操作日志记录(一)

除springMvc外需要引入@Aspect注解依赖: 定义切面类: 切面类可根据业务要求自行添加逻辑 在spring的容器xml中添加配置: 此处有个注意点:网上说利用AOP无法拦截controller层,经测试,需要...

晓泊 ⋅ 05/08 ⋅ 0

聊聊Dubbo - Dubbo可扩展机制源码解析

摘要: 在Dubbo可扩展机制实战中,我们了解了Dubbo扩展机制的一些概念,初探了Dubbo中LoadBalance的实现,并自己实现了一个LoadBalance。是不是觉得Dubbo的扩展机制很不错呀,接下来,我们就...

阿里云云栖社区 ⋅ 06/05 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

破解公司回应苹果“USB限制模式”:已攻破

本周四,苹果发表声明称 iOS 中加入了一项名为“USB 限制模式”的功能,可以防止 iPhone 在连接其他设备的时候被破解,并且强调这一功能并不是针对 FBI 等执法部门,为的是保护用户数据安全。...

六库科技 ⋅ 30分钟前 ⋅ 0

MyBtais整合Spring Boot整合,TypeHandler对枚举类(enum)处理

概要 问题描述 我想用枚举类来表示用户当前状态,枚举类由 code 和 msg 组成,但我只想把 code 保存到数据库,查询处理,能知道用户当前状态,这应该怎么做呢?在 Spring 整合MyBatis 的时候...

Wenyi_Feng ⋅ 49分钟前 ⋅ 0

redis安装记录

自行学习记录吧,有来自网络学习过程和调整不是照搬的 第一步:下载redis安装包 wget http://download.redis.io/releases/redis-4.0.10.tar.gz 第二步:解压压缩包 tar -zxvf redis-4.0.10.t...

cavion ⋅ 55分钟前 ⋅ 0

synchronized与Lock的区别

# <center>王梦龙的读书笔记第一篇</center> ## <center>-synchronized与Lock的区别</centre> ###一、从使用场景来说 + synchronized 是能够注释代码块、类、方法但是它的加锁是和解锁使用一......

我不想加班 ⋅ 今天 ⋅ 0

VConsole的使用

手机端控制台打印输出,方便bug的排查。 首先需要引入vconsole.min.js 文件,然后在文件中创造实例。就能直接使用了。 var vConsole = new VConsole(); vConsole的文件地址...

大美琴 ⋅ 今天 ⋅ 0

Java NIO之字符集

1 字符集和编解码的概念 首先,解释一下什么是字符集。顾名思义,就是字符的集合。它的初衷是把现实世界的符号映射为计算机可以理解的字节。比如我创造一个字符集,叫做sex字符集,就包含两个...

士别三日 ⋅ 今天 ⋅ 0

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 今天 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 今天 ⋅ 0

Webpack 4 api 了解与使用

webpack 最近升级到了 v4.5+版 01 官方不再支持 node4 以下版本 官方不再支持 node4 以下版本官方不再支持 node4 以下的版本,所以如果你的node版本太低,先开始升级node吧!话说node10 ...

NDweb ⋅ 今天 ⋅ 0

数据结构与算法之魔术师发牌问题

一、魔术师发牌问题 1.问题描述 魔术师利用一副牌中的13张黑牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:“我不看牌,只数数就可以猜到每张牌是什么。”魔术师把最上面的那张牌数为...

aibinxiao ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部