
Tip: 什么是匿名类
即没有名称的类,其名称由Java编译器给出,一般为:外部类名称+$+匿名类顺序,名称也就是其他地方不能引用,不能实例化,只用一次,当然也就不能有构造器。
在ProxyFactoryBean中,需要为target目标对象生成Proxy代理对象,从而为AOP横切面的编织做好准备。从FactoryBean中获取对象,是以getObject()方法作为入口完成的。在该方法中,首先对通知器链进行初始化,封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备。在生成代理对象时,因为Spring中有singleton类型和prototype类型这两种不同的Bean,所以要对代理对象的生成做一个区分。
首先为Proxy代理对象配置Advisor链,在initializeAdvisorChain()方法中执行。
在该方法中它会首先通过this.advisorChainInitialized来判断通知器链是否已经初始化了,如果已经初始化了,就直接返回。其他情况下,通过 this.interceptorNames 来要添加的通知器名,然后通过该名从IOC容器中取得的通知器加入到拦截器链中。
生成singleton的代理对象在getSingletonInstance()中完成
如果它还没有被创建,则lazily creating
在Spring代理目标target时,其实并不是直接创建一个目标target的对象实例的,而是通过一个TargetSource类型的对象对目标target进行封装,Spring Aop获取目标对象始终是通过 TargetSource.getTarget() 方法进行的。
proxy(代理对象)代理的不是target,而是TargetSource
那么问题来了:为什么SpringAOP代理不直接代理target,而需要通过代理TargetSource(target的来源,其内部持有target),间接代理target呢?
通常情况下,一个proxy(代理对象)只能代理一个target,每次方法调用的目标也是唯一固定的target。但是,如果让proxy代理TargetSource,可以使得每次方法调用的target实例都不同(当然也可以相同,这取决于TargetSource实现)。这种机制使得方法调用变得灵活,可以扩展出很多高级功能,如:target pool(目标对象池)、hot swap(运行时目标对象热替换),等等。
Spring内置了多种TargetSource
监听调用AdvisedSupportListener实现类的activated方法
具体的代理对象的生成,是在ProxyFactoryBean的基类AdvisedSupport的实现中借助AopProxyFactory完成的,这个代理对象要么从JDK中生成,要么借助CGLIB获得。
这个AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactor。
如果targetClass是接口类,使用JDK来生成Proxy
如果不是接口类要生成Proxy,那么使用CGLIB来生成。
接下来分别介绍两种不同的方式来产生AopProxy代理对象
首先从advised对象中取得代理对象的代理接口配置,然后调用Proxy的newProxyInstance方法,得到最终的Proxy代理对象。
在生成代理对象时,需要指明三个参数,类加载器,代理接口和Proxy回调方法所在的对象。
在回调方法所在对象中,需要实现InvocationHandler接口,它定义了invoke方法,
对于JdkDynamimcAopProxy,它本身实现了InvocationHandler接口和invoke方法,这个invoke方法是Proxy代理对象的回调方法。
在该篇文章中就不讲解了,感兴趣的可以百度搜索。
注:本文大多数是对《Spring技术内幕》的阅读整理。
ioc就是控制翻转或是依赖注入。通俗的讲就是如果在什么地方需要一个对象,你自己不用去通过new 生成你需要的对象,而是通过spring的bean工厂为你长生这样一个对象。aop就是面向切面的编程。比如说你每做一次对数据库 *** 作,都要生成一句日志。如果,你对数据库的 *** 作有很多类,那你每一类中都要写关于日志的方法。但是如果你用aop,那么你可以写一个方法,在这个方法中有关于数据库 *** 作的方法,每一次调用这个方法的时候,就加上生成日志的 *** 作。
说的不是很清晰,多写多看就能明白了。
需求:在不停止服务的情况下,通过上传一个jar包然后捕获某方法的异常进行处理
思路:
使用springaop实现
至于为什么要定义一个切入点到service包下面的所以方法,感兴趣的可以研究一下springAop的源码,里面有个postProcessBeforeInstantiation方法,会返回代理对象,如果没有则不会返回代理对象。
当然还有一种思路,就是在动态添加切入点的时候把spring容器中的对象替换成自己的代理对象(没有实验过,在非单例模式的时候有问题,这里不深入研究)。
引入aop的starter:
第一步:
第二步:
jar包怎么写?只需要实现对应的切面方法就行了
通常有方法前拦截,方法后拦截,以及异常拦截。通过在这些拦截中编写自己的业务处理,可以达到特定的需求。
execution表达式
20200401:添加注入applicationContext到jar里面
https://github.com/cdInit/aopHotPlugin
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)