-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path655d86b3.html
281 lines (265 loc) · 60.9 KB
/
655d86b3.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Spring AOP | 实现一个小目标</title><meta name="keywords" content="Java,Spring"><meta name="author" content="我想打游戏,[email protected]"><meta name="copyright" content="我想打游戏"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="AOP 术语在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码、日志代码、事务控制代码、性能监控代码。 名词 解释 Joinpoint(连接点) 它指的是那些可以用于把增强代码加入到业务主线中的点。在方法执行的前后通过动态代理技术加入增强的代码。在 Spring 框架 AOP 思想的技术实现中,也只支持方法类型的连接点。 Pointcut(切入点) 它指的是那">
<meta property="og:type" content="article">
<meta property="og:title" content="Spring AOP">
<meta property="og:url" content="https://blog.990304.xyz/655d86b3.html">
<meta property="og:site_name" content="实现一个小目标">
<meta property="og:description" content="AOP 术语在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码、日志代码、事务控制代码、性能监控代码。 名词 解释 Joinpoint(连接点) 它指的是那些可以用于把增强代码加入到业务主线中的点。在方法执行的前后通过动态代理技术加入增强的代码。在 Spring 框架 AOP 思想的技术实现中,也只支持方法类型的连接点。 Pointcut(切入点) 它指的是那">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://s2.loli.net/2022/10/09/IoNOM4PifrBpZ67.png">
<meta property="article:published_time" content="2022-03-21T05:22:55.000Z">
<meta property="article:modified_time" content="2022-10-09T05:53:51.670Z">
<meta property="article:author" content="我想打游戏">
<meta property="article:tag" content="Java">
<meta property="article:tag" content="Spring">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://s2.loli.net/2022/10/09/IoNOM4PifrBpZ67.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.990304.xyz/655d86b3"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//hm.baidu.com"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.min.css" media="print" onload="this.media='all'"><script>var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?a6a8fe63a57ca303dd1117df5f602aec";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: undefined,
translate: {"defaultEncoding":1,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"简"},
noticeOutdate: undefined,
highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
copy: {
success: '复制成功',
error: '复制错误',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: true,
post: true
},
runtime: '天',
date_suffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: undefined,
lightbox: 'fancybox',
Snackbar: undefined,
source: {
justifiedGallery: {
js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
}
},
isPhotoFigcaption: true,
islazyload: false,
isAnchor: true
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: 'Spring AOP',
isPost: true,
isHome: false,
isHighlightShrink: false,
isToc: true,
postUpdate: '2022-10-09 13:53:51'
}</script><noscript><style type="text/css">
#nav {
opacity: 1
}
.justified-gallery img {
opacity: 1
}
#recent-posts time,
#post-meta time {
display: inline !important
}
</style></noscript><script>(win=>{
win.saveToLocal = {
set: function setWithExpiry(key, value, ttl) {
if (ttl === 0) return
const now = new Date()
const expiryDay = ttl * 86400000
const item = {
value: value,
expiry: now.getTime() + expiryDay,
}
localStorage.setItem(key, JSON.stringify(item))
},
get: function getWithExpiry(key) {
const itemStr = localStorage.getItem(key)
if (!itemStr) {
return undefined
}
const item = JSON.parse(itemStr)
const now = new Date()
if (now.getTime() > item.expiry) {
localStorage.removeItem(key)
return undefined
}
return item.value
}
}
win.getScript = url => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
script.onerror = reject
script.onload = script.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
script.onload = script.onreadystatechange = null
resolve()
}
document.head.appendChild(script)
})
win.activateDarkMode = function () {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
win.activateLightMode = function () {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
const t = saveToLocal.get('theme')
if (t === 'dark') activateDarkMode()
else if (t === 'light') activateLightMode()
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
if (asideStatus === 'hide') {
document.documentElement.classList.add('hide-aside')
} else {
document.documentElement.classList.remove('hide-aside')
}
}
const detectApple = () => {
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
document.documentElement.classList.add('apple')
}
}
detectApple()
})(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://s2.loli.net/2022/09/28/iEBxunMYAGHODFz.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">20</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">6</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">6</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 清单</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/movies/"><i class="fa-fw fas fa-video"></i><span> 电影</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友情链接</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://s2.loli.net/2022/10/09/IoNOM4PifrBpZ67.png')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">实现一个小目标</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 清单</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/music/"><i class="fa-fw fas fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/movies/"><i class="fa-fw fas fa-video"></i><span> 电影</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友情链接</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">Spring AOP</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-03-21T05:22:55.000Z" title="发表于 2022-03-21 13:22:55">2022-03-21</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-10-09T05:53:51.670Z" title="更新于 2022-10-09 13:53:51">2022-10-09</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">Java 学习笔记</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Java-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/Spring-%E6%A1%86%E6%9E%B6/">Spring 框架</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">3k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>11分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Spring AOP"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="AOP-术语"><a href="#AOP-术语" class="headerlink" title="AOP 术语"></a>AOP 术语</h1><p>在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码、日志代码、事务控制代码、性能监控代码。<br><img src="https://s2.loli.net/2022/10/09/IoNOM4PifrBpZ67.png" alt="image.png"><br><br></p>
<table>
<thead>
<tr>
<th>名词</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>Joinpoint(连接点)</td>
<td>它指的是那些可以用于把增强代码加入到业务主线中的点。在方法执行的前后通过动态代理技术加入增强的代码。在 Spring 框架 AOP 思想的技术实现中,也只支持方法类型的连接点。</td>
</tr>
<tr>
<td>Pointcut(切入点)</td>
<td>它指的是那些已经把增强代码加入到业务主线进来之后的连接点。由上图中,我们看出表现层 register 方法就只是连接点,因为判断访问权限的功能并没有对其增强。</td>
</tr>
<tr>
<td>Advice(通知/增强)</td>
<td>它指的是切面类中用于提供增强功能的方法。并且不同的方法增强的时机是不一样的。比如,开启事务肯定要在业务方法执行之前执行;提交事务要在业务方法正常执行之后执行,而回滚事务要在业务方法执行产生异常之后执行等等。这些就是通知的类型。其分类有:前置通知 后置通知 异常通知 最终通知 环绕通知。</td>
</tr>
<tr>
<td>Target(目标对象)</td>
<td>它指的是代理的目标对象。即被代理对象。</td>
</tr>
<tr>
<td>Proxy(代理)</td>
<td>它指的是一个类被 AOP 织入增强后,产生的代理类。即代理对象。</td>
</tr>
<tr>
<td>Weaving(织 入)</td>
<td>它指的是把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。</td>
</tr>
<tr>
<td>Aspect(切面)</td>
<td>它指定是增强的代码所关注的方面,把这些相关的增强代码定义到一个类中,这个类就是切面类。例如,事务切面,它里面定义的方法就是和事务相关的,像开启事务,提交事务,回滚事务等等,不会定义其他与事务无关的方法。我们前面的案例中 TrasnactionManager 就是一个切面。</td>
</tr>
</tbody></table>
<p>Aspect 切面 = 切入点 + 通知<br>Aspect 切面 = 切入点(锁定方法)+ 方位点(锁定方法中的特殊时机)+ 横切逻辑</p>
<p><strong>众多的概念,目的就是为了锁定要在哪个地方插入什么横切逻辑代码。</strong></p>
<h1 id="AspectJ-切入点表达式"><a href="#AspectJ-切入点表达式" class="headerlink" title="AspectJ 切入点表达式"></a>AspectJ 切入点表达式</h1><ul>
<li>关键字:execution(表达式)</li>
<li>表达式:<ul>
<li>访问修饰符返回值包名.包名…类名.方法名(参数列表)</li>
</ul>
</li>
<li>标准写法示例:<ul>
<li>public void li.service.impl.AccountServiceImpl.saveAccount()</li>
</ul>
</li>
<li>访问修饰符可以省略<ul>
<li>void li.service.impl.AccountServiceImpl.saveAccount()</li>
</ul>
</li>
<li>返回值可以使用通配符,表示任意返回值<ul>
<li>* li.service.impl.AccountServiceImpl.saveAccount()</li>
</ul>
</li>
<li>包名可以使用通配符,表示任意包,但是有几级包就需要写几个*.<ul>
<li>* *.*.*.AccountServiceImpl.saveAccount()</li>
</ul>
</li>
<li>包名可以使用..表示当前包及其子包<ul>
<li>* *..AccountServiceImpl.saveAccount()</li>
</ul>
</li>
<li>类名和方法名都可以使用 * 实现通配<ul>
<li>* *..*.*()</li>
</ul>
</li>
<li>参数列表:<ul>
<li>可以直接写数据类型:<ul>
<li>基本类型直接写名称 int</li>
<li>引用类型写包名.类名 java.lang.String</li>
</ul>
</li>
<li>可以使用通配符,表示任意类型,但是必须有参数</li>
<li>可以使用..有无参数均可,有参数可以是任意类型</li>
</ul>
</li>
<li>全通配写法:<ul>
<li>* *..*.*(..)</li>
</ul>
</li>
<li>实际开发中切入点表达式的通常写法:<ul>
<li>切到业务层实现类下的所有方法 li.service.impl.*.*(..)</li>
</ul>
</li>
</ul>
<h1 id="五种通知类型"><a href="#五种通知类型" class="headerlink" title="五种通知类型"></a>五种通知类型</h1><h2 id="前置通知"><a href="#前置通知" class="headerlink" title="前置通知"></a>前置通知</h2><p>配置方式:aop:before 标签</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--</span></span><br><span class="line"><span class="comment"> 作用:用于配置前置通知。</span></span><br><span class="line"><span class="comment"> 出现位置:它只能出现在aop:aspect标签内部</span></span><br><span class="line"><span class="comment"> 属性:</span></span><br><span class="line"><span class="comment"> method:用于指定前置通知的方法名称</span></span><br><span class="line"><span class="comment"> pointcut:用于指定切入点表达式</span></span><br><span class="line"><span class="comment"> pointcut-ref:用于指定切入点表达式的引用</span></span><br><span class="line"><span class="comment"> arg-names:用于指定通知方法的参数名称,要求表达式中必须有描述 args 的语句</span></span><br><span class="line"><span class="comment">--></span></span><br><span class="line"><span class="tag"><<span class="name">aop:before</span> <span class="attr">method</span>=<span class="string">"beforeMethod"</span> <span class="attr">pointcut-ref</span>=<span class="string">"pt1"</span>/></span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">beforeMethod</span><span class="params">(JoinPoint joinPoint)</span> {</span><br><span class="line"> Object[] args = joinPoint.getArgs();</span><br><span class="line"> <span class="keyword">for</span> (Object arg : args) {</span><br><span class="line"> System.out.println(arg);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(<span class="string">"业务逻辑之前..."</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>执行时机:在切入点方法(业务核心方法)执行之前执行。<br>说明:前置通知可以获取切入点方法的参数,并对其进行增强。</p>
<h2 id="后置通知"><a href="#后置通知" class="headerlink" title="后置通知"></a>后置通知</h2><p>配置方式:aop:after-returning 标签</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--</span></span><br><span class="line"><span class="comment"> 作用:用于配置后置正常执行通知</span></span><br><span class="line"><span class="comment"> 出现位置:它只能出现在aop:aspect标签内部</span></span><br><span class="line"><span class="comment"> 属性:</span></span><br><span class="line"><span class="comment"> method:用于指定前置通知的方法名称</span></span><br><span class="line"><span class="comment"> pointcut:用于指定切入点表达式</span></span><br><span class="line"><span class="comment"> pointcut-ref:用于指定切入点表达式的引用</span></span><br><span class="line"><span class="comment"> arg-names:用于指定通知方法的参数名称,要求表达式中必须有描述 args 的语句</span></span><br><span class="line"><span class="comment"> returning:用于指定返回值</span></span><br><span class="line"><span class="comment">--></span></span><br><span class="line"><span class="tag"><<span class="name">aop:after-returning</span> <span class="attr">method</span>=<span class="string">"afterMethod"</span> <span class="attr">pointcut-ref</span>=<span class="string">"pt1"</span> <span class="attr">returning</span>=<span class="string">"result"</span>/></span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterMethod</span><span class="params">(JoinPoint joinPoint, Object result)</span> {</span><br><span class="line"> Object[] args = joinPoint.getArgs();</span><br><span class="line"> <span class="keyword">for</span> (Object arg : args) {</span><br><span class="line"> System.out.println(arg);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(<span class="string">"业务逻辑之后..."</span> + result);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>执行时机:在切入点方法(业务核心方法)正常执行之后执行,出现异常后后置正常执行通知不再执行了,而是执行异常通知。<br>说明:后置通知即可以获取切入点方法的参数,也可以获取切入点方法的返回值。</p>
<h2 id="异常通知"><a href="#异常通知" class="headerlink" title="异常通知"></a>异常通知</h2><p>配置方式:aop:after-throwing 标签</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--</span></span><br><span class="line"><span class="comment"> 作用:用于配置后置异常执行通知</span></span><br><span class="line"><span class="comment"> 出现位置:它只能出现在aop:aspect标签内部</span></span><br><span class="line"><span class="comment"> 属性:</span></span><br><span class="line"><span class="comment"> method:用于指定前置通知的方法名称</span></span><br><span class="line"><span class="comment"> pointcut:用于指定切入点表达式</span></span><br><span class="line"><span class="comment"> pointcut-ref:用于指定切入点表达式的引用</span></span><br><span class="line"><span class="comment"> arg-names:用于指定通知方法的参数名称,要求表达式中必须有描述 args 的语句</span></span><br><span class="line"><span class="comment"> throwing:用于指定异常通知中异常的变量名称</span></span><br><span class="line"><span class="comment">--></span></span><br><span class="line"><span class="tag"><<span class="name">aop:after-throwing</span> <span class="attr">method</span>=<span class="string">"afterMethod"</span> <span class="attr">pointcut-ref</span>=<span class="string">"pt1"</span>/></span></span><br></pre></td></tr></table></figure>
<p>执行时机:在切入点方法(业务核心方法)执行产生异常之后执行,如果没有出现异常则不会执行。<br>说明:异常通知即可以获取切入点方法的参数,也可以获取切入点方法执行产生的异常信息。</p>
<h2 id="最终通知"><a href="#最终通知" class="headerlink" title="最终通知"></a>最终通知</h2><p>配置方式:aop:after-throwing 标签</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--</span></span><br><span class="line"><span class="comment"> 作用:用于指定最终通知</span></span><br><span class="line"><span class="comment"> 出现位置:它只能出现在aop:aspect标签内部</span></span><br><span class="line"><span class="comment"> 属性:</span></span><br><span class="line"><span class="comment"> method:用于指定前置通知的方法名称</span></span><br><span class="line"><span class="comment"> pointcut:用于指定切入点表达式</span></span><br><span class="line"><span class="comment"> pointcut-ref:用于指定切入点表达式的引用</span></span><br><span class="line"><span class="comment"> arg-names:用于指定通知方法的参数名称,要求表达式中必须有描述 args 的语句</span></span><br><span class="line"><span class="comment">--></span></span><br><span class="line"><span class="tag"><<span class="name">aop:after</span> <span class="attr">method</span>=<span class="string">"finalMethod"</span> <span class="attr">pointcut-ref</span>=<span class="string">"pt1"</span>/></span></span><br></pre></td></tr></table></figure>
<p>执行时机:最终通知的执行时机是在切入点方法(业务核心方法)执行完成之后,切入点方法返回之前执行。 换句话说,无论切入点方法执行是否产生异常,它都会在返回之前执行。<br>说明:最终通知执行时,可以获取到通知方法的参数。同时它可以做一些清理操作。</p>
<h2 id="环绕通知"><a href="#环绕通知" class="headerlink" title="环绕通知"></a>环绕通知</h2><p>配置方式:aop:after-throwing 标签</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--</span></span><br><span class="line"><span class="comment"> 作用:用于指定最终通知</span></span><br><span class="line"><span class="comment"> 出现位置:它只能出现在aop:aspect标签内部</span></span><br><span class="line"><span class="comment"> 属性:</span></span><br><span class="line"><span class="comment"> method:用于指定前置通知的方法名称</span></span><br><span class="line"><span class="comment"> pointcut:用于指定切入点表达式</span></span><br><span class="line"><span class="comment"> pointcut-ref:用于指定切入点表达式的引用</span></span><br><span class="line"><span class="comment"> arg-names:用于指定通知方法的参数名称,要求表达式中必须有描述 args 的语句</span></span><br><span class="line"><span class="comment">--></span></span><br><span class="line"><span class="tag"><<span class="name">aop:around</span> <span class="attr">method</span>=<span class="string">"aroundMethod"</span> <span class="attr">pointcut-ref</span>=<span class="string">"pt1"</span>/></span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> Object <span class="title function_">aroundMethod</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span> {</span><br><span class="line"> Object result;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Object[] args = proceedingJoinPoint.getArgs();</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的前置通知..."</span>);</span><br><span class="line"> result = proceedingJoinPoint.proceed(args);</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的后置通知..."</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (Throwable e) {</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的异常通知..."</span>);</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(e);</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的最终通知..."</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>执行时机:Spring 框架为我们提供了一个接口 ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法。<br>说明:可以控制原有逻辑是否执行。</p>
<h1 id="使用-Spring-AOP-的方式"><a href="#使用-Spring-AOP-的方式" class="headerlink" title="使用 Spring AOP 的方式"></a>使用 Spring AOP 的方式</h1><h2 id="XML-方式"><a href="#XML-方式" class="headerlink" title="XML 方式"></a>XML 方式</h2><h3 id="xml-文件头"><a href="#xml-文件头" class="headerlink" title="xml 文件头"></a>xml 文件头</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"utf-8"</span> ?></span></span><br><span class="line"><span class="tag"><<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">"http://www.springframework.org/schema/beans"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:context</span>=<span class="string">"http://www.springframework.org/schema/context"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:aop</span>=<span class="string">"http://www.springframework.org/schema/aop"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"</span></span></span><br><span class="line"><span class="string"><span class="tag"> http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag"> https://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag"> http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="string"><span class="tag"> https://www.springframework.org/schema/context/spring-context.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag"> http://www.springframework.org/schema/aop</span></span></span><br><span class="line"><span class="string"><span class="tag"> https://www.springframework.org/schema/aop/spring-aop.xsd"</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">beans</span>></span></span><br></pre></td></tr></table></figure>
<h3 id="配置横切逻辑-bean"><a href="#配置横切逻辑-bean" class="headerlink" title="配置横切逻辑 bean"></a>配置横切逻辑 bean</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"logUtils"</span> <span class="attr">class</span>=<span class="string">"com.lagou.edu.utils.LogUtils"</span>/></span></span><br></pre></td></tr></table></figure>
<h3 id="使用-aop-config-标签开始-aop-的配置"><a href="#使用-aop-config-标签开始-aop-的配置" class="headerlink" title="使用 aop:config 标签开始 aop 的配置"></a>使用 aop:config 标签开始 aop 的配置</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--配置 aop 的过程其实就是把 aop 相关概念落地--></span></span><br><span class="line"><span class="comment"><!--aspect(切面) = 切入点(方法) + 方位点(方法中的特殊时机) + 横切逻辑--></span></span><br><span class="line"><span class="tag"><<span class="name">aop:config</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">aop:aspect</span> <span class="attr">id</span>=<span class="string">"logAspect"</span> <span class="attr">ref</span>=<span class="string">"logUtils"</span>></span></span><br><span class="line"> <span class="comment"><!--切入点锁定需要通知的方法,使用 aspectj 语法表达式--></span></span><br><span class="line"> <span class="tag"><<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">"pt1"</span> <span class="attr">expression</span>=<span class="string">"execution(public void com.lagou.edu.service.impl.TransferServiceImpl.transfer(String,String,int))"</span>/></span></span><br><span class="line"></span><br><span class="line"> <span class="comment"><!--方位点,pointcut-ref 关联切入点,pointcut 可以直接写aspectj 语法表达式--></span></span><br><span class="line"> <span class="tag"><<span class="name">aop:before</span> <span class="attr">method</span>=<span class="string">"beforeMethod"</span> <span class="attr">pointcut-ref</span>=<span class="string">"pt1"</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">aop:aspect</span>></span></span><br><span class="line"><span class="tag"></<span class="name">aop:config</span>></span></span><br></pre></td></tr></table></figure>
<h3 id="改变代理方式的配置"><a href="#改变代理方式的配置" class="headerlink" title="改变代理方式的配置"></a>改变代理方式的配置</h3><p>Spring 在选择创建代理对象时,会根据被代理对象的实际情况来选择。被代理对象实现了接口,则采用基于接口的动态代理。当被代理对象没有实现任何接口的时候,Spring会自动切换到基于子类的动态代理方式。<br>无论被代理对象是否实现接口,只要不是 final 修饰的类都可以采用 cglib 提供的方式创建代理对象。所以 Spring 也考虑到了这个情况,提供了配置的方式实现强制使用基于子类的动态代理(即cglib的方式),配置的方式有两种:</p>
<ul>
<li>使用 aop:config 标签配置<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">aop:config</span> <span class="attr">proxy-target-class</span>=<span class="string">"true"</span>></span></span><br></pre></td></tr></table></figure></li>
<li>使用 aop:aspectj-autoproxy 标签配置<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--此标签是基于 XML 和注解组合配置 AOP 时的必备标签,表示 Spring 开启注解配置 AOP 的支持--></span></span><br><span class="line"><span class="tag"><<span class="name">aop:aspectj-autoproxy</span> <span class="attr">proxy-target-class</span>=<span class="string">"true"</span>></span><span class="tag"></<span class="name">aop:aspectj-autoproxy</span>></span></span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="XML-注解方式"><a href="#XML-注解方式" class="headerlink" title="XML + 注解方式"></a>XML + 注解方式</h2><p>XML 中开启 Spring 对注解 AOP 的支持</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">aop:aspectj-autoproxy</span>/></span></span><br></pre></td></tr></table></figure>
<p>Java 代码示例</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogUtils</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Pointcut("execution(* com.lagou.edu.service..*.*(..))")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">pointCut</span><span class="params">()</span> {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Before("pointCut()")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">beforeMethod</span><span class="params">(JoinPoint joinPoint)</span> {</span><br><span class="line"> Object[] args = joinPoint.getArgs();</span><br><span class="line"> <span class="keyword">for</span> (Object arg : args) {</span><br><span class="line"> System.out.println(arg);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(<span class="string">"业务逻辑之前..."</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@AfterReturning(value = "pointCut()", returning = "result")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterMethod</span><span class="params">(JoinPoint joinPoint, Object result)</span> {</span><br><span class="line"> Object[] args = joinPoint.getArgs();</span><br><span class="line"> <span class="keyword">for</span> (Object arg : args) {</span><br><span class="line"> System.out.println(arg);</span><br><span class="line"> }</span><br><span class="line"> System.out.println(<span class="string">"业务逻辑之后..."</span> + result);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@AfterThrowing("pointCut()")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">exceptionMethod</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"业务逻辑异常..."</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@After("pointCut()")</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">finalMethod</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"业务逻辑结束..."</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Around("pointCut()")</span></span><br><span class="line"> <span class="keyword">public</span> Object <span class="title function_">aroundMethod</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span> {</span><br><span class="line"> Object result;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Object[] args = proceedingJoinPoint.getArgs();</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的前置通知..."</span>);</span><br><span class="line"> result = proceedingJoinPoint.proceed(args);</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的后置通知..."</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (Throwable e) {</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的异常通知..."</span>);</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(e);</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> System.out.println(<span class="string">"环绕通知的最终通知..."</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="注解方式"><a href="#注解方式" class="headerlink" title="注解方式"></a>注解方式</h2><p>在使用注解驱动开发 aop 时,是用注解替换掉配置文件中的下面这行配置</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">aop:aspectj-autoproxy</span>/></span></span><br></pre></td></tr></table></figure>
<p>在配置类中使用如下注解替换上述配置</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableAspectJAutoProxy</span> <span class="comment">//开启spring对注解AOP的支持</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringConfig</span> {</span><br><span class="line">}</span><br></pre></td></tr></table></figure></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="https://blog.990304.xyz">我想打游戏</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://blog.990304.xyz/655d86b3.html">https://blog.990304.xyz/655d86b3.html</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://blog.990304.xyz" target="_blank">实现一个小目标</a>!</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Java/">Java</a><a class="post-meta__tags" href="/tags/Spring/">Spring</a></div><div class="post_share"><div class="social-share" data-image="https://s2.loli.net/2022/10/09/IoNOM4PifrBpZ67.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/eb6b454e.html"><img class="prev-cover" src="https://s2.loli.net/2022/09/28/xklYGdNOp2Jfo8s.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Spring 声明式事务</div></div></a></div><div class="next-post pull-right"><a href="/b2a79ee.html"><img class="next-cover" src="https://s2.loli.net/2022/09/28/JprRdkWTvwMh68u.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Spring IoC 高级特性</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/aad19206.html" title="Bean 创建流程"><img class="cover" src="https://s2.loli.net/2022/10/08/8REn1yjfUVaKosF.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-21</div><div class="title">Bean 创建流程</div></div></a></div><div><a href="/7aea873f.html" title="BeanFactory 创建流程"><img class="cover" src="https://s2.loli.net/2022/10/08/1TbhpYeOIfgsU3Q.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-18</div><div class="title">BeanFactory 创建流程</div></div></a></div><div><a href="/690a266d.html" title="Spring IoC 容器初始化主体流程"><img class="cover" src="https://img-blog.csdnimg.cn/1b40502ab717476ba8ee7df0931ea527.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-15</div><div class="title">Spring IoC 容器初始化主体流程</div></div></a></div><div><a href="/adc3e213.html" title="Spring Bean 的作用范围及生命周期"><img class="cover" src="https://img-blog.csdnimg.cn/46d42e4c19b2427da2b3e31453263650.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-05-19</div><div class="title">Spring Bean 的作用范围及生命周期</div></div></a></div><div><a href="/cbde7b0b.html" title="Spring IoC 循环依赖问题"><img class="cover" src="https://img-blog.csdnimg.cn/3aa3e44f116944ef9b10b4dd735c156a.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-30</div><div class="title">Spring IoC 循环依赖问题</div></div></a></div><div><a href="/b2a79ee.html" title="Spring IoC 高级特性"><img class="cover" src="https://s2.loli.net/2022/09/28/JprRdkWTvwMh68u.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-03-20</div><div class="title">Spring IoC 高级特性</div></div></a></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://s2.loli.net/2022/09/28/iEBxunMYAGHODFz.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">我想打游戏</div><div class="author-info__description">记录一些生活趣事</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">20</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">6</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">6</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/guziwen-lab"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/guziwen-lab/" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:[email protected]" target="_blank" title="Email"><i class="fas fa-envelope"></i></a><a class="social-icon" href="https://blog.csdn.net/qq_30087395/" target="_blank" title="Csdn"><i class="fa-solid fa-rss"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">欢迎大家</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#AOP-%E6%9C%AF%E8%AF%AD"><span class="toc-number">1.</span> <span class="toc-text">AOP 术语</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#AspectJ-%E5%88%87%E5%85%A5%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-number">2.</span> <span class="toc-text">AspectJ 切入点表达式</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BA%94%E7%A7%8D%E9%80%9A%E7%9F%A5%E7%B1%BB%E5%9E%8B"><span class="toc-number">3.</span> <span class="toc-text">五种通知类型</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E7%BD%AE%E9%80%9A%E7%9F%A5"><span class="toc-number">3.1.</span> <span class="toc-text">前置通知</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%90%8E%E7%BD%AE%E9%80%9A%E7%9F%A5"><span class="toc-number">3.2.</span> <span class="toc-text">后置通知</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%BC%82%E5%B8%B8%E9%80%9A%E7%9F%A5"><span class="toc-number">3.3.</span> <span class="toc-text">异常通知</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%9C%80%E7%BB%88%E9%80%9A%E7%9F%A5"><span class="toc-number">3.4.</span> <span class="toc-text">最终通知</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%8E%AF%E7%BB%95%E9%80%9A%E7%9F%A5"><span class="toc-number">3.5.</span> <span class="toc-text">环绕通知</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-Spring-AOP-%E7%9A%84%E6%96%B9%E5%BC%8F"><span class="toc-number">4.</span> <span class="toc-text">使用 Spring AOP 的方式</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#XML-%E6%96%B9%E5%BC%8F"><span class="toc-number">4.1.</span> <span class="toc-text">XML 方式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#xml-%E6%96%87%E4%BB%B6%E5%A4%B4"><span class="toc-number">4.1.1.</span> <span class="toc-text">xml 文件头</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E6%A8%AA%E5%88%87%E9%80%BB%E8%BE%91-bean"><span class="toc-number">4.1.2.</span> <span class="toc-text">配置横切逻辑 bean</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-aop-config-%E6%A0%87%E7%AD%BE%E5%BC%80%E5%A7%8B-aop-%E7%9A%84%E9%85%8D%E7%BD%AE"><span class="toc-number">4.1.3.</span> <span class="toc-text">使用 aop:config 标签开始 aop 的配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%94%B9%E5%8F%98%E4%BB%A3%E7%90%86%E6%96%B9%E5%BC%8F%E7%9A%84%E9%85%8D%E7%BD%AE"><span class="toc-number">4.1.4.</span> <span class="toc-text">改变代理方式的配置</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#XML-%E6%B3%A8%E8%A7%A3%E6%96%B9%E5%BC%8F"><span class="toc-number">4.2.</span> <span class="toc-text">XML + 注解方式</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B3%A8%E8%A7%A3%E6%96%B9%E5%BC%8F"><span class="toc-number">4.3.</span> <span class="toc-text">注解方式</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/6e9746c4.html" title="CentOS 安装翰高数据库"><img src="https://s2.loli.net/2023/03/13/UucfkBIRYxCd7Tm.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="CentOS 安装翰高数据库"/></a><div class="content"><a class="title" href="/6e9746c4.html" title="CentOS 安装翰高数据库">CentOS 安装翰高数据库</a><time datetime="2023-03-13T08:08:54.000Z" title="发表于 2023-03-13 16:08:54">2023-03-13</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/e56c5c4.html" title="可移动硬盘内的AppImage应用如何获取移动硬盘内的资源"><img src="https://s2.loli.net/2022/10/01/fnwLNigZCUG7bTd.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="可移动硬盘内的AppImage应用如何获取移动硬盘内的资源"/></a><div class="content"><a class="title" href="/e56c5c4.html" title="可移动硬盘内的AppImage应用如何获取移动硬盘内的资源">可移动硬盘内的AppImage应用如何获取移动硬盘内的资源</a><time datetime="2023-02-02T03:31:45.000Z" title="发表于 2023-02-02 11:31:45">2023-02-02</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/49140f59.html" title="把Java程序打包为AppImage格式"><img src="https://s2.loli.net/2023/01/12/SczgAwsmhU3ltF4.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="把Java程序打包为AppImage格式"/></a><div class="content"><a class="title" href="/49140f59.html" title="把Java程序打包为AppImage格式">把Java程序打包为AppImage格式</a><time datetime="2023-01-12T01:09:32.000Z" title="发表于 2023-01-12 09:09:32">2023-01-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/ff0917f7.html" title="流量控制与可靠传输"><img src="https://s2.loli.net/2022/10/04/EQqN6dK9YDFJmhj.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="流量控制与可靠传输"/></a><div class="content"><a class="title" href="/ff0917f7.html" title="流量控制与可靠传输">流量控制与可靠传输</a><time datetime="2022-10-04T15:00:44.000Z" title="发表于 2022-10-04 23:00:44">2022-10-04</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/a5d2d7c3.html" title="Mybaits 架构原理"><img src="https://s2.loli.net/2022/10/01/46p5Emr3uRMd7vo.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Mybaits 架构原理"/></a><div class="content"><a class="title" href="/a5d2d7c3.html" title="Mybaits 架构原理">Mybaits 架构原理</a><time datetime="2022-10-01T05:24:18.000Z" title="发表于 2022-10-01 13:24:18">2022-10-01</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2022 - 2023 By 我想打游戏</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">简</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>