【spring源码学习】spring的AOP面向切面编程的实现解析
动态代理解析:https://blog.csdn.net/wonking666/article/details/79542820
一:Advice(通知)
(1)定义在连接点做什么,为切面增强提供织入接口。在spring aop中主要描述围绕方法调用而注入的切面行为。
(2)spring定义了几个时刻织入增强行为的接口
=>org.springframework.aop.BeforeAdvice
org.springframework.aop.MethodBeforeAdvice
=>org.springframework.aop.AfterAdvice
org.springframework.aop.AfterReturningAdvice
=>org.springframework.aop.ThrowsAdvice
二:PointCut(切点)
(1)决定Advice应该作用那些连接点。也就是说通过PointCut来定义需要增强的方法集合。
(2)spring定义的PointCut的接口
=>org.springframework.aop.Pointcut
=>org.springframework.aop.TruePointcut
=> org.springframework.aop.support.JdkRegexpMethodPointcut
(3)相关接口。PointCut接口会返回两个对象,一个ClassFilter,一个是MethodMatcher
=>org.springframework.aop.ClassFilter
=>org.springframework.aop.TrueClassFilter
=>org.springframework.aop.MethodMatcher 匹配当前方法是否需要执行增强逻辑,也就是是否需要执行Advice接口的方法。
=>org.springframework.aop.TrueMethodMatcher
三:通知器皿(Advisor)
(1)完成对目标方法的切面增强设计(advice)和关注点的设计(PoinCut)以后,需要一个对象把他们结合起来,完成这个作用的就是(Advisor)
(2)spring定义的Advisor接口
=>org.springframework.aop.Advisor
=>org.springframework.aop.PointcutAdvisor
=>org.springframework.aop.support.DefaultPointcutAdvisor
(3)Advisor的控制器的接口
=>org.springframework.aop.framework.adapter.AdvisorAdapter
=>org.springframework.aop.framework.adapter.AfterReturningAdviceAdapter 目标方法执行完执行该增强的控制器
=>org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter 目标方法未执行前执行该增强的控制器
=>org.springframework.aop.framework.adapter.ThrowsAdviceAdapter 目标方法执行过程抛出异常执行该增强的控制器
四:springAop的相关
(1)springAop的核心技术是动态代理。动态代理的技术是jdk的一个特征。
(2)springAop的代理对象生成案例
=>org.springframework.aop.framework.ProxyFactoryBean
=>org.springframework.aop.framework.ProxyFactory
五:ProxyFactoryBean的工作流程。
(1)实现FactoryBean接口的类,在想IOC容器申请bean的时候,其实返回的是该类执行getObject()方法的返回。
(2)ProxyFactoryBean的getObject()方法返回的是目标对象的代理对象。
其执行过程
=>根据配置的interceptorNames的属性值先初始化代理增强的链子.根据interceptorNames从IOC容器中得到增强类的bean,然后判断其类型,形成DefaultPointcutAdvisor对象。
=>根据配置的targetName属性值从IOC容器中得到目标对象的bean,形成一个SingletonTargetSource对象。
=>将其本身作为一个aop代理对象创建的数据配置类,创建一个动态代理对象,返回给ioc容器申请。
(3)在执行目标对象的方法过程中,会根据执行的方法的对象,从代理链子里找到所有的Advisor对象,然后利用其属性Pointcut对象获取ClassFilter, MethodMatcher来判断当前Advisor是否要执行。如果执行,则加入执行代理链子中。以jdk动态代理为例子,是org.springframework.aop.framework.JdkDynamicAopProxy类中invoke(Object proxy, Method method, Object[] args)方法中这句代码List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);。该句代码中this.advised其实就是ProxyFactoryBean本身。
六案例
一:Advice的对象
package com.mobile.thinks.aop.advice;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class LoginBeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] args, Object target)throws Throwable {
System.out.println("LoginBeforeAdvice.before()执行方法为==>"+method.getName());
System.out.println("LoginBeforeAdvice.before()执行参数为==>"+args);
System.out.println("LoginBeforeAdvice.before()执行的目标为==>"+target.getClass());
}
}
二:目标对象
package com.mobile.thinks.service.impl; import java.util.Date; import org.springframework.stereotype.Service; import com.mobile.thinks.entity.User;
import com.mobile.thinks.service.UserInfoService; @Service(value="userInfoServiceImpl")
public class UserInfoServiceImpl implements UserInfoService{ @Override
public User loginByUserNameAndPassWord(String userName, String passWord) {
User user=new User(); user.setAddress("三门峡");
user.setAge(28);
user.setCreateTime(new Date());
user.setName(userName);
return user;
} }
三:配置文件
<!-- 测试ProxyFactoryBean -->
<!--定义一个advice -->
<bean name="loginBeforeAdvice" class="com.mobile.thinks.aop.advice.LoginBeforeAdvice" />
<!-- 定义FactoryBean -->
<bean name="userInfoService" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 要代理的目标对象,在ioc容器中的名字 -->
<property name="targetName">
<value>userInfoServiceImpl</value>
</property>
<!-- 要植入增强功能的advice在IOC容器中的名字 -->
<property name="interceptorNames">
<list><value>loginBeforeAdvice</value></list>
</property>
</bean>
七:spring内部基于该中方式实现动态代理的案例。spring提供的HttpInvoker远程调用.可以阅读该类getObject方法。实现对Facade接口代理
org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean
==============================spring的自动进行对bean进行代理的创建类===============================
1、org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
2、上述类是org.springframework.beans.factory.config.BeanPostProcessor接口的实现类
3、ioc在创建bean时,postProcessAfterInstantiation会执行方法,并对当前bean检查,是否需要代理。
4、检查逻辑,每一个切面,都会有自己的Pointcut,去适配当前的bean。需要则动态代理,不需要则返回。
事务管理实现动态代理的切面:
事务代理的切面:org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor
pointcut的类:org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut
事务增强的类:org.springframework.transaction.interceptor.TransactionInterceptor
==============================spring的具体实现===============================
1、Advisor包换了Advice和Pointcut
2、Advice里是面向切面的增强逻辑实现
3、Pointcut里包含了ClassFilter和MethodMatcher。通过对类进行过滤或者方法进行过滤,决定一个类是否需要进行动态代理,添加增强逻辑。

1、spring容器中会注册:org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator
该类是org.springframework.beans.factory.config.BeanPostProcessor的实现,该类会在客户端向spring申请bean的时候,进行代理类的创建,
2、向spring容器中获取所有实现advisor接口的List<Advisor>。
3、org.springframework.aop.support.AopUtils类的findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz)
根据当前要被创建的bean的Class和beanName,去适配所有的List<Advisor>,看那些是适合当前bean的增强。
先根据advisor中的Pointcut的ClassFilter和MethodMatcher的方法决定
先根据ClassFilter决定,如ClassFilter决定不了,则根据MethodMatcher匹配bean的所有方法,包括接口和继承的类的方法。
4、通过2,3步确定那些List<Advisor>可以对当前bean进行动态代理增强,然后进行代理类的创建。
org.springframework.aop.framework.JdkDynamicAopProxy(代理类的执行入口)
org.springframework.aop.framework.ProxyFactory(所有适合当前List<Advisor>进行增强的信息会被存储到proxyFactory中)
org.springframework.aop.framework.AdvisedSupport是ProxyFactory的父类
spring的动态代理实现的基本逻辑
1、从ioc容器中找到所有实现了Advisor接口的bean,并将其缓存
2、扫描:每初始化一个bean,进行扫描的时候,都要用spring容器里的每一个Advisor里的Pointcut进行过滤,看当前类的是否需要进行增强。如果需要,把匹配通过的Advisor形成一个集合。
3、扫描后,如果返回的Advisor集合里不为空,说明该类需要代理,则创建代理对象。并将每一个Advisor里的Advice作为增强加入的增强链条中。(advice有排序功能,决定那个增强先被代理执行)
jdk动态代理的分析:https://www.cnblogs.com/huansky/p/9573202.html
【spring源码学习】spring的AOP面向切面编程的实现解析的更多相关文章
- spring源码学习之路---AOP初探(六)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近工作很忙,但当初打算学习 ...
- spring源码学习——spring整体架构和设计理念
Spring是在Rod Johnson的<Expert One-On-One J2EE Development and Design >的基础上衍生而来的.主要目的是通过使用基本的java ...
- 重新学习之spring第二个程序,配置AOP面向切面编程
第一步:在配置好的ioc容器的基础上,导入面向切面编程所需要的jar包 (本案例用的是spring3.2.4,由于spring3.2.4的官网jar包中不再有依赖包,所以依赖包都是从网上找的) 第二步 ...
- Spring 源码学习(4) —— 动态AOP使用示例
在实际工作中, 此bean可能是满足业务需要的核心逻辑, 例如test()方法中可能会封装着某个核心业务, 如果在test()方法前后加入日志来跟踪调试, 直接修改源码并不符合面向对象的设计模式, 而 ...
- Spring源码学习
Spring源码学习--ClassPathXmlApplicationContext(一) spring源码学习--FileSystemXmlApplicationContext(二) spring源 ...
- Spring 源码学习——Aop
Spring 源码学习--Aop 什么是 AOP 以下是百度百科的解释:AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程通过预编译的方式和运行期动态代理实 ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- spring源码学习之路---深入AOP(终)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章和各位一起看了一下sp ...
- spring源码学习之路---IOC初探(二)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章当中我没有提及具体的搭 ...
随机推荐
- CSS3飘带状3D菜单
在线演示 本地下载
- 混合开发的大趋势之一React Native之Image (脑动理解)
文章是宝宝自己写的,你可以转走,标明哪来的就行王亟亟的大牛之路 国庆这些天要么旅游要么WOW,感觉整个人都废了.. 直接从黄种人晒成了非洲大酋长..然而还是无橙,这礼拜要做7天,昨天把单元测试的东西整 ...
- Android解决软键盘弹出将布局顶到上面
有时候我们在下面的布局是一个RadioGroup,然后当页面中的EditText获得焦点的时候,会将地步的RadioGroup顶起来,这时候我们只需要在AndroidMainfest中RadioGro ...
- virtualbox ubuntu下ssh连接
一.首先Ubuntu中安装ssh服务器 Ubuntu 下安装 OpenSSH Server 是无比轻松的一件事情,需要的命令只有一条: sudo apt-get install openssh-ser ...
- 【C#笔札】1 string类型
C中没有string这个类型,而是用字符串数组来实现,相对来说比较麻烦. LABVIEW相对来说要简单太多,毕竟他主要的精力集中在硬件控制上,软件操作方面极其简单. C#类似,C#中有System.S ...
- WPF 通过 CommandParameter 传递当前窗体到 ViewModel
在应用 Command 模式中,需要在View上点击 一个按钮,需要将当前窗体作为参数传递为 command 两种方式传递当前窗体1.通过窗体名称(假设窗体名称为 ThisWindow) < ...
- Django进阶Template篇001 - 常用模板标签及过滤器
一.模板的组成 HTML代码+逻辑控制代码 二.逻辑控制代码的组成 1.变量(使用双大括号来引用变量) {{ var_name }} 2.标签(tag)的使用(使用大括号和百分号的组成来表示使用tag ...
- 查看SQLServer的最大连接数
如何查看SQLServer的最大连接数?相信很多人对个很有兴趣,一下就给出两种方法: 1. 查询服务器属性 默认服务设置为0(表示不受限制). 2. SQL查看最大连接数 这里的32767就是服务器的 ...
- 【转】安装OS X虚拟机错误vcpu-0:VERIFY vmcore/vmm/main/physMem_monitor.c:1123
新建一个虚拟机, 选择客户机操作系统为Apple MacOS X 10.10, 其余参数可以默认. 注意建好之后不要急着打开客户机, 因为直接打开你会发现新建的客户机将会无法启动. 仔细阅读Mac O ...
- 【scala】集和映射
Scala同时提供了集(Set)和映射(Map)的可变和不可变的不同选择,但使用同样的简单名字,可以通过类继承的关系来区分可变和不可变版本. 如图所示,左边的为不可变集,右边的为可变集. //我们创建 ...