- 浏览: 4928305 次
- 性别:
- 来自: 南京
文章分类
- 全部博客 (2844)
- java (1094)
- hadoop (37)
- jvm (39)
- hbase (11)
- sql (25)
- 异常 (83)
- div css (6)
- 数据库 (95)
- 有趣的code (15)
- struts2 (6)
- spring (124)
- js (44)
- 算法 (65)
- linux (36)
- hibernate (7)
- 中间件 (78)
- 设计模式 (2)
- 架构 (275)
- 操作系统 (91)
- maven (35)
- tapestry (1)
- mybatis (9)
- MQ (101)
- zookeeper (18)
- 搜索引擎,爬虫 (208)
- 分布式计算 (45)
- c# (7)
- 抓包 (28)
- 开源框架 (45)
- 虚拟化 (12)
- mongodb (15)
- 计算机网络 (2)
- 缓存 (97)
- memcached (6)
- 分布式存储 (13)
- scala (5)
- 分词器 (24)
- spark (104)
- 工具 (23)
- netty (5)
- Mahout (6)
- neo4j (6)
- dubbo (36)
- canal (3)
- Hive (10)
- Vert.x (3)
- docker (115)
- 分布式追踪 (2)
- spring boot (5)
- 微服务 (56)
- 淘客 (5)
- mesos (67)
- php (3)
- etcd (2)
- jenkins (4)
- nginx (7)
- 区块链 (1)
- Kubernetes (92)
- 驾照 (1)
- 深度学习 (15)
- JGroups (1)
- 安全 (5)
- 测试 (16)
- 股票 (1)
- Android (2)
- 房产 (1)
- 运维 (6)
- 网关 (3)
最新评论
-
明兜3号:
部署落地+业务迁移 玩转k8s进阶与企业级实践技能(又名:Ku ...
Kubernetes系统常见运维技巧 -
q328965539:
牛掰啊 资料收集的很全面
HDFS小文件处理解决方案总结+facebook(HayStack) + 淘宝(TFS) -
guichou:
fluent挂载了/var/lib/kubelet/pods目 ...
kubernetes上部署Fluentd+Elasticsearch+kibana日志收集系统 -
xu982604405:
System.setProperty("java.r ...
jmx rmi 穿越防火墙问题及jmxmp的替代方案 -
大漠小帆:
麻烦问下,“获取每个Item相似性最高的前N个Item”,这个 ...
协同过滤推荐算法在MapReduce与Spark上实现对比
在spring中有两种产生代理对象的方式:
AopProxy的子类:Cglib2AopProxy和JdkDynamicAopProxy。
1. Jdk主要是:Proxy.newProxyInstance(classLoader, proxiedInterfaces, InvocationHandler);
2. Cglib则是通过Enhancer类来实现的。
它们有个相同点就是都有一个回调方法。我们可以在回调方法中对目标方法进行增强。
JDK代理对象的回调
1. public Object invoke(Object proxy, Method method, Object[]
2. args) throws Throwable {
3. MethodInvocation invocation = null;
4. Object oldProxy = null;
5. boolean setProxyContext = false;
6. TargetSource targetSource =
7. this.advised.targetSource;
8. Class targetClass = null;
9. Object target = null;
10. try {
11. if (!this.equalsDefined &&
12. AopUtils.isEqualsMethod(method)) {
13. // The target does not implement the
14. equals(Object) method itself.
15. return equals(args[0]);
16. }
17. if (!this.hashCodeDefined &&
18. AopUtils.isHashCodeMethod(method)) {
19. // The target does not implement the
20. hashCode() method itself.
21. return hashCode();
22. }
23. if (!this.advised.opaque &&
24. method.getDeclaringClass().isInterface() &&
25.
26. method.getDeclaringClass().isAssignableFrom(Advised.class))
27. {
28. // Service invocations on
29. ProxyConfig with the proxy config...
30. return
31. AopUtils.invokeJoinpointUsingReflection(this.advised,
32. method, args);
33. }
34. Object retVal = null;
35. if (this.advised.exposeProxy) {
36. // Make invocation available if
37. necessary.
38. oldProxy =
39. AopContext.setCurrentProxy(proxy);
40. setProxyContext = true;
41. }
42. /**
43. * May be null. Get as late as possible to
44. minimize the time we "own" the
45. * target, in case it comes from a pool.
46. */
47. //得到目标对象的地方。
48. target = targetSource.getTarget();
49. if (target != null) {
50. targetClass = target.getClass();
51. }
52. // Get the interception chain for this
53. method.
54. // 这里获得定义好的拦截器链。
55. List chain =
56. this.advised.getInterceptorsAndDynamicInterception
57. Advice(method, targetClass);
58. /**
59. * Check whether we have any advice. If we
60. don't, we can fallback on
61. * direct reflective invocation of the
62. target, and avoid creating a MethodInvocation.
63. */
64.
65. //
66. 如果没有设定拦截器,那么我们就直接调用target的对应方法。
67. if (chain.isEmpty()) {
68. /**
69. * We can skip creating a
70. MethodInvocation: just invoke the target directly
71. * Note that the final invoker must
72. be an InvokerInterceptor so we
73. * know it does nothing but a
74. reflective operation on the target, and no hot
75. * swapping or fancy proxying.
76. */
77. retVal =
78. AopUtils.invokeJoinpointUsingReflection(target, method,
79. args);
80. }
81. else {
82. // We need to create a method
83. invocation...
84. /**
85. *
86. 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相
87. 应方法,
88. *
89. 通过构造一个ReflectiveMethodInvocation来实现,下面我们会看
90. *
91. 这个ReflectiveMethodInvocation类的具体实现。
92. */
93. invocation = new
94. ReflectiveMethodInvocation(proxy, target, method,
95. args, targetClass, chain);
96. // Proceed to the joinpoint through
97. the interceptor chain.
98. //沿着拦截器链继续前进。
99. retVal = invocation.proceed();
100. }
101.
102. // Massage return value if necessary.
103. if (retVal != null && retVal == target &&
104. method.getReturnType().
105. isInstance(Proxy) &&
106. !RawTargetAccess.class.isAssignableFrom
107. (method.getDeclaringClass())) {
108. /**
109. * Special case: it returned "this"
110. and the return type of the method
111. * is type-compatible. Note that we
112. can't help if the target sets
113. * a reference to itself in another
114. returned object.
115. */
116. retVal = Proxy;
117. }
118. return retVal;
119. }
120. finally {
121. if (target != null &&
122. !targetSource.isStatic()) {
123. // Must have come from TargetSource.
124. targetSource.releaseTarget(target);
125. }
126. if (setProxyContext) {
127. // Restore old proxy.
128.
129. AopContext.setCurrentProxy(oldProxy);
130. }
131. }
132. }
Cglib代理对象的回调方法:
1. public Object intercept(Object proxy, Method method,
2. Object[] args, MethodProxy
3. methodProxy) throws Throwable {
4. Object oldProxy = null;
5. boolean setProxyContext = false;
6. Class targetClass = null;
7. Object target = null;
8. try {
9. if (this.advised.exposeProxy) {
10. // Make invocation available if
11. necessary.
12. oldProxy =
13. AopContext.setCurrentProxy(proxy);
14. setProxyContext = true;
15. }
16. /**
17. * May be
null
. Get as late as
18. possible to minimize the time we
19. * "own" the target, in case it comes from a
20. pool.
21. */
22. target = getTarget();
23. if (target != null) {
24. targetClass = target.getClass();
25. }
26. //从advised中取得配置好的AOP通知。
27. List chain =
28. this.advised.getInterceptorsAndDynamicInterceptionAdvice
29. (method, targetClass);
30. Object retVal = null;
31. /**
32. * Check whether we only have one
33. InvokerInterceptor: that is,
34. * no real advice, but just reflective
35. invocation of the target.
36. */
37. //
38. 如果没有AOP通知配置,那么直接调用target对象的调用方法。
39. if (chain.isEmpty() &&
40. Modifier.isPublic(method.getModifiers())) {
41. /**
42. * We can skip creating a
43. MethodInvocation: just invoke the target directly.
44. * Note that the final invoker must
45. be an InvokerInterceptor, so we know
46. * it does nothing but a reflective
47. operation on the target, and no hot
48. * swapping or fancy proxying.
49. */
50. retVal = methodProxy.invoke(target,
51. args);
52. }
53. else {
54.
55. //通过CglibMethodInvocation来启动advice通知。
56. retVal = new
57. CglibMethodInvocation(proxy, target, method, args,
58. targetClass, chain, methodProxy).proceed();
59. }
60. retVal = massageReturnTypeIfNecessary(proxy,
61. target, method, retVal);
62. return retVal;
63. }
64. finally {
65. if (target != null) {
66. releaseTarget(target);
67. }
68. if (setProxyContext) {
69. // Restore old proxy.
70.
71. AopContext.setCurrentProxy(oldProxy);
72. }
73. }
74. }
在调用代理目标对象的方法时;都对方法进行了增强。
75. //从advised中取得配置好的AOP通知。
76. List chain =
77. this.advised.getInterceptorsAndDynamicInterceptionAdvice
(method, targetClass);
在这里可以设置不同的拦截器进行不同的业务处理。比如记录日志,事物的开启…
这就是Aop的核心。具体是由相关的拦截器完成的。
在jdk,cglib代理类中都有一个拦截链处理器,它们分别是
JDK代理类拦截链处理器:
133. 这个ReflectiveMethodInvocation类的具体实现。
134. */
135. ReflectiveMethodInvocation invocation = new
136. ReflectiveMethodInvocation(proxy, target, method,
137. args, targetClass, chain);
138. //沿着拦截器链继续前进。
retVal = invocation.proceed();
CGLIB代理类拦截链处理器:
78. //通过CglibMethodInvocation来启动advice通知。
79. retVal = new
80. CglibMethodInvocation(proxy, target, method, args,
81. targetClass, chain, methodProxy).proceed();
82. }
83. retVal = massageReturnTypeIfNecessary(proxy,
84. target, method, retVal);
JDK代理类拦截链处理器的proceed方法:
1. public Object proceed() throws Throwable {
2. // We start with an index of -1 and increment
3. early.
4. /**
5. *如果拦截器链中的拦截器迭代调用完毕,这里开始调用tar
6. get的函数,
7. *这个函数是通过反射机制完成的,具体实现在:AopUtils.
8. invokeJoinpointUsingReflection方法里面。
9. */
10. if (this.currentInterceptorIndex ==
11. this.interceptorsAndDynamicMethod
12. Matchers.size() - 1) {
13. return invokeJoinpoint();
14. }
15. //这里沿着定义好的
16. interceptorOrInterceptionAdvice链进行处理。
17. Object interceptorOrInterceptionAdvice =
18. this.interceptorsAndDynamicMethodMatchers.get(++this
19. .currentInterceptor
20. Index);
21. if (interceptorOrInterceptionAdvice instanceof
22. InterceptorAndDynamic
23. MethodMatcher) {
24. /**
25. * Evaluate dynamic method matcher here:
26. static part will already have
27. * been evaluated and found to match.
28. */
29. /**
30.
31. *这里对拦截器进行动态匹配的判断,还记得我们前面分析的pointcu
32. t吗?
33.
34. *这里是触发进行匹配的地方,如果和定义的pointcut匹配,那么这
35. 个advice将会得到执行。
36. */
37. InterceptorAndDynamicMethodMatcher dm =
38. (InterceptorAndDynamicMethodMatcher)
39. interceptorOrInterceptionAdvice;
40. if (dm.methodMatcher.matches(this.method,
41. this.targetClass, this.arguments)) {
42. return dm.interceptor.invoke(this);
43. }
44. else {
45. // Dynamic matching failed.
46. // Skip this interceptor and invoke
47. the next in the chain.
48. //
49. 如果不匹配,那么proceed会被递归调用,直到所有的拦截器都被运
50. 行过为止。
51. return proceed();
52. }
53. }
发表评论
-
spring session序列化问题排查
2017-12-01 19:07 6144严重: Servlet.service() for ser ... -
spring mvc统一异常处理(@ControllerAdvice + @ExceptionHandler)
2017-12-01 17:09 2936spring 封装了非常强大的异常处理机制。本文选取@Co ... -
springboot注解
2017-12-01 09:44 965@RestController和@RequestMappin ... -
Spring 4 xml 注解配置谅解
2017-12-01 09:39 1056《Spring in Action》4th E ... -
利用junit对springMVC的Controller进行测试
2017-11-30 16:26 1395平时对junit测试service/D ... -
spring cloud config实现datasource的热部署
2017-11-21 16:44 1573关于spring cloud config的基本使用,前面的 ... -
Spring+MyBatis实现数据库读写分离方案
2017-11-20 17:15 1016百度关键词:spring mybatis 多数据源 读写分离 ... -
spring session 退出登录 清理session
2017-11-10 09:26 6391/** * Allows creating an ... -
spring http session 监听 创建 失效session
2017-11-15 09:35 4812一.流程概述 主要是通过扩展ServletRequest ... -
spring session spring:session:sessions:expires 源码跟踪
2017-11-14 09:37 1433/** * Saves any attribut ... -
spring session 考虑问题解答
2017-11-09 09:50 603相关问题 2.Redis容量考虑,由于spring see ... -
spring 获取bean 测试
2017-11-09 09:51 611package com.jayway.springsess ... -
spring父子容器与读取properties文件
2017-11-09 09:51 786读取properties文件中的内容,可以使用@Value ... -
Spring在代码中获取bean的几种方式
2017-11-08 09:46 1164方法一:在初始化时保存ApplicationContext对 ... -
Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
2017-11-08 09:41 780解释一: 要想很好理解这三个上下文的关系,需 ... -
Spring以及SPringmvc相关问题: ServletContext -父子容器
2017-11-08 09:41 578总结如下: 明确了Servlet规范中Servl ... -
DelegatingFilterProxy
2017-11-08 09:48 1152摘要: 配置过滤器代理类,通过spring配置的bean来 ... -
DelegatingFilterProxy-api
2017-11-09 09:51 509为什么用DelegatingFilterProxy ... -
spring的启动过程——spring和springMVC父子容器的原理
2017-11-15 09:29 673要想很好理解这三个上下文的关系,需要先熟悉spri ... -
spring中bean被多次实例化问题
2017-11-13 09:33 51371. 描述 spring中提供了两种主要方式实例化bea ...
相关推荐
2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到Spring 2.5 2.7.1. 改变 2.8. 更新的样例应用 2.9. ...
2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到Spring 2.5 2.7.1. 改变 2.8. 更新的样例应用 2.9. ...
6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
:如同spring容器那样,实现了反转控制和依赖注入功能,作为应用程序中对象的容器,它可将Bean单例化,并为Bean提供代理,在切面处增强功能,不过目前只支持事务,此外,这样的框架也能很好地解耦模块之间的关系,并...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
JSEditor 是 Eclipse 下编辑 JavaScript 源码的插件,提供语法高亮以及一些通用的面向对象方法。 Java数据库连接池 BoneCP BoneCP 是一个高性能的开源java数据库连接池实现库。它的设计初衷就是为了提高数据库连接...
动态调用对象的属性和方法——性能和灵活性兼备的方法 消除由try/catch语句带来的warning 微软的应试题完整版(附答案) 一个时间转换的问题,顺便谈谈搜索技巧 .net中的正则表达式使用高级技巧 (一) C#静态成员和...