javascript
SpringTest2
Spring?框架第二天?AOP切面編程?
今天重點(diǎn)內(nèi)容:
1、?什么是AOP???AOP實(shí)現(xiàn)原理是怎樣的??AOP相關(guān)術(shù)語?
2、?AOP底層實(shí)現(xiàn)?(了解)?-----?JDK動(dòng)態(tài)代理、?Cglib動(dòng)態(tài)代理?
3、?傳統(tǒng)Spring?AOP?編程?(了解實(shí)現(xiàn),掌握使用?)
4、?基于AspectJ?框架,實(shí)現(xiàn)spring2.0之后?AOP?編程(重點(diǎn))
5、?Spring?JdbcTemplate?模板工具類?使用?(ORM?解決方案?)---?類似Apache?DbUtils
?
1.??AOP面向切面編程概述
1.1.??什么是AOP??
l?AOP?Aspect?Oriented?Programing?面向切面編程?
1)?一種程序設(shè)計(jì)思想?
2)?
3)?AOP是OOP?(Object?Oriented?Programing?)延伸?
?
l?思想:AOP采取橫向抽取機(jī)制,取代了傳統(tǒng)縱向繼承體系重復(fù)性代碼(性能監(jiān)視、事務(wù)管理、安全檢查、緩存)
?
AOP底層就是代理的增強(qiáng)?!?
?
?
l?面試題:在項(xiàng)目哪些功能使用AOP???---?AOP使用場(chǎng)景
1、性能監(jiān)視?(方法運(yùn)行時(shí)間)
2、事務(wù)管理?
3、安全檢查?(權(quán)限?)
4、緩存優(yōu)化?(第一次訪問,查詢數(shù)據(jù),放入緩存,?第二次以后訪問?從緩存返回?)
5、記錄日志?
?
?
l?學(xué)習(xí)AOP?分為兩個(gè)部分?
1、?學(xué)習(xí)傳統(tǒng)Spring?AOP編程?(Spring1.2年代?)
?
2、?學(xué)習(xí)AspectJ?框架的AOP編程?(Spring2.0以后年代?)
?
1.2.??AOP開發(fā)術(shù)語?
?
?
切面由切入點(diǎn)和通知組成!?
2.??AOP的底層實(shí)現(xiàn)(了解)
2.1.??JDK?動(dòng)態(tài)代理機(jī)制
1、必須針對(duì)接口進(jìn)行代理?
2、生成代理對(duì)象,通過Proxy類?
?
進(jìn)行代理?,傳入目標(biāo)對(duì)象類加載器、?目標(biāo)對(duì)象接口?、?處理類?
3、自己實(shí)現(xiàn)InvocationHandler?接口?
?
對(duì)目標(biāo)對(duì)象方法調(diào)用時(shí),都會(huì)執(zhí)行invoke方法,起到攔截作用?
?
第一步:?編寫業(yè)務(wù)接口和實(shí)現(xiàn)類
?
第二步:?編寫傳統(tǒng)調(diào)用,編寫基于代理調(diào)用?
//?生成代理工具類
public?class?JdkProxyFactory?implements?InvocationHandler{
?
//?目標(biāo)對(duì)象
private?Object?target;
?
public?JdkProxyFactory(Object?target)?{
this.target?=?target;
}
?
//?創(chuàng)建代理對(duì)象
public?Object?createJdkProxy(){
return?Proxy.newProxyInstance(
target.getClass().getClassLoader(),?
target.getClass().getInterfaces(),?
this);
}
?
@Override
public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{
//?記錄日志
System.out.println("日志記錄:"?+?method.getName()?+?"執(zhí)行了...");
return?method.invoke(target,?args);
}
}
第三步:?測(cè)試代碼
?
2.2.??Cglib動(dòng)態(tài)代理機(jī)制?
JDK只能對(duì)接口進(jìn)行代理,如果目標(biāo)對(duì)象沒有接口,無法使用JDK動(dòng)態(tài)代理?----?使用cglib?
什么是cglib???
CGLIB(Code?Generation?Library)是一個(gè)開源項(xiàng)目!是一個(gè)強(qiáng)大的,高性能,高質(zhì)量的Code生成類庫,它可以在運(yùn)行期擴(kuò)展Java類與實(shí)現(xiàn)Java接口。
Cglib可以對(duì)接口或者類進(jìn)行代理?!
?
使用Spring最新版本開發(fā),無需單獨(dú)下載cglib?(spring?core?已經(jīng)集成cglib?)
Cglib開發(fā)依賴?asm的jar?(spring?core?已經(jīng)集成?asm?)
?
?
1、?編寫目標(biāo)業(yè)務(wù)類?
?
2、編寫Cglib?生成代理工廠類?
?
//?生成cglib代理工廠
public?class?CglibProxyFactory?implements?MethodInterceptor?{
?
//?目標(biāo)對(duì)象
private?Object?target;
?
public?CglibProxyFactory(Object?target)?{
this.target?=?target;
}
?
//?生成代理對(duì)象方法
public?Object?createCglibProxy()?{
//?通過Enhancer?生成代理
Enhancer?enhancer?=?new?Enhancer();
//?設(shè)置超類
//?生成UserDAO的子類
enhancer.setSuperclass(target.getClass());
//?設(shè)置回調(diào)處理類
enhancer.setCallback(this);
//?生成代理返回
return?enhancer.create();
}
?
@Override
/**
?*?proxy?代理對(duì)象
?*?method?方法反射對(duì)象
?*?args?參數(shù)
?*?methodProxy?方法的代理對(duì)象,用于執(zhí)行父類的方法?
?*/
public?Object?intercept(Object?proxy,?Method?method,?Object[]?args,?MethodProxy?methodProxy)?throws?Throwable?{
System.out.println("cglib?日志:?調(diào)用了"?+?method.getName()?+?"方法...");
//?return?method.invoke(target,?args);
return?methodProxy.invokeSuper(proxy,?args);//?調(diào)用真實(shí)對(duì)象方法
}
}
?
3、編寫測(cè)試類?
?
小結(jié):?
Spring?AOP?就是基于JDKProxy?和?CglibProxy?
1、如果目標(biāo)對(duì)象有接口,優(yōu)先使用JDK?Proxy
2、如果目標(biāo)對(duì)象沒有接口,?使用CglibProxy?
3.??傳統(tǒng)Spring?AOP?切面編程?
傳統(tǒng)?:?Spring1.2?開始支持AOP編程?(這種編程,現(xiàn)在自己寫的很少,但是我們會(huì)用到?)
Spring?AOP編程,必須學(xué)習(xí)切入點(diǎn)和通知?
1)?切入點(diǎn),通過配置完成的
2)?通知,通過編程完成的?
3.1.??傳統(tǒng)AOP編程,通知類型(5種)
?
不同Advice?執(zhí)行增強(qiáng)代碼的時(shí)間點(diǎn)不同?!?
3.2.??編寫一個(gè)Advice?
1、?導(dǎo)入jar包?
傳統(tǒng)Spring?AOP開發(fā)?
- com.springsource.org.aopalliance-1.0.0.jar?AOP聯(lián)盟定義接口規(guī)范
- spring-aop-3.2.0.RELEASE.jar?Spring對(duì)AOP擴(kuò)展支持?
整合AspectJ?AOP開發(fā)
- com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar?第三方AspectJ?包
- spring-aspects-3.2.0.RELEASE.jar?Spring?對(duì)AspectJ?擴(kuò)展支持?
?
?
2、?編寫Advice?實(shí)現(xiàn)?MethodInterceptor?環(huán)繞增強(qiáng)?
?
?
3.3.??AspectJ?切入點(diǎn)語法?
為什么要學(xué)習(xí)AspectJ切入點(diǎn)語法??
傳統(tǒng)AOP切入點(diǎn)?,使用正則表達(dá)式語法,現(xiàn)在基本上不去用?
?
Spring沒有支持所有AspectJ語法,所以我們學(xué)習(xí)Spring?AOP?只能spring文檔?!
?
?
AspectJ切入點(diǎn),是通過函數(shù)進(jìn)行配置?
l?execution?執(zhí)行
n?語法:execution(<訪問修飾符>?<返回類型><方法名>(<參數(shù)>)<異常>)
execution(*?*(..))??第一個(gè)*?任意返回類型?,?第二個(gè)*?任意方法名?,?..?任意參數(shù)?
execution(*?cn.itcast.service.UserService.*(..))?匹配UserService所有方法?
execution(*?cn.itcast.service.UserService+.*(..))?匹配UserService子類所有方法?
execution(*?cn.itcast.service..*.*(..))?第一個(gè)..?任意子包?*.*任何類的任何方法?
l?within?根據(jù)包匹配
n?語法:within(包名..*)?
within(cn.itcast.service..*)?攔截service下所有類的方法?
l?this根據(jù)目標(biāo)類型匹配
n?語法:this(類名)?
this(cn.itcast.service.UserService)?攔截?UserService所有方法?(包括代理對(duì)象)
l?target?根據(jù)目標(biāo)類型匹配
n?語法?:target(類名)
target(cn.itcast.service.UserService)?攔截UserService所有方法?(不包括代理對(duì)象?)
l?args?根據(jù)參數(shù)匹配
args(java.lang.String)?攔截所有參數(shù)為String類的方法?
l?bean?根據(jù)bean?name匹配?
bean(userService)?攔截bean?id/name為userService對(duì)象所有方法?
3.4.??配置傳統(tǒng)Spring?AOP切面
1、?引入aop的命名空間?
<beans?xmlns="http://www.springframework.org/schema/beans"
???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???????xmlns:aop="http://www.springframework.org/schema/aop"
???????xsi:schemaLocation="
http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop?http://www.springframework.org/schema/aop/spring-aop.xsd">
?
<!--?bean?definitions?here?-->
?
</beans>
?
?
2、?配置切面?
?
?
3、編寫測(cè)試
?
?
圖解:
?
注意:?需要對(duì)有接口實(shí)現(xiàn)類直接代理,不對(duì)接口代理?!
?
4.??AspectJ?AOP切面編程(XML配置)
Spring1.2?開始支持AOP編程,主要代理對(duì)象創(chuàng)建通過ProxyFactoryBean構(gòu)造?!
后來人們發(fā)現(xiàn)spring1.2?AOP開發(fā)太麻煩了,spring2.0?引入對(duì)AspectJ(第三方AOP框架)支持,AOP開發(fā)就被簡化了。?
?
4.1.??AspectJ支持通知類型?(6種)
?
相比傳統(tǒng)AOP編程,多了一個(gè)After通知(最終通知,?效果finally?)
4.2.??Before前置通知使用?
分析前置通知應(yīng)用場(chǎng)景:?權(quán)限控制、?記錄訪問日志?
第一步:?編寫Advice?
?
第二步:?配置切入點(diǎn)和切面?
?
?
面試題:?advisor和?aspect的區(qū)別???
Advisor是傳統(tǒng)Spring?AOP?切面,只能有一個(gè)通知和一個(gè)切入點(diǎn)
Aspect?是AspectJ?提供切面,可以包括多個(gè)通知和多個(gè)切入點(diǎn)
?
面試題:?aspect和aspectJ區(qū)別??
aspect?切面,?由切入點(diǎn)和通知組成
aspectJ?框架,進(jìn)行AOP開發(fā)?
?
=====================?擴(kuò)展?struts2?攔截器機(jī)制是AOP思想嗎??
1、?訪問Action?進(jìn)行代理?ActionProxy?
2、?提供Interceptor?類似Advice?增強(qiáng)?,通過配置使不同Action訪問前執(zhí)行不同攔截器
?
4.3.??AfterReturing?后置通知使用
在目標(biāo)類的方法運(yùn)行之后,進(jìn)行代碼增強(qiáng)?
特性:操作目標(biāo)方法返回值 ?
?
使用AspectJ?框架開發(fā),可以將多個(gè)增強(qiáng)的方法,寫在同一個(gè)類里面?!
第一步:?編寫增強(qiáng)方法
?
第二步:?配置applicationContext.xml?
?
4.4.??Around?環(huán)繞通知使用?
在目標(biāo)類方法?執(zhí)行前和執(zhí)行后,都可以增強(qiáng)?
場(chǎng)景:?1)?運(yùn)行方法時(shí)間監(jiān)控?2)?事務(wù)管理?3)?權(quán)限控制?4)?緩存?5)?日志?
?
第一步:?編寫Advice增強(qiáng)方法?
?
?
第二步:?配置切入點(diǎn)和切面?
?
4.5.??AfterThrowing?拋出通知使用?
在目標(biāo)發(fā)生異常時(shí),執(zhí)行增強(qiáng)代碼?
場(chǎng)景:?目標(biāo)方法異常,日志記錄異常,將異常信息發(fā)送郵件給管理員?
第一步:?編寫拋出增強(qiáng)方法?
?
?
第二步:?配置切入點(diǎn)和切面?
?
當(dāng)發(fā)生異常時(shí),?目標(biāo)方法后置通知不會(huì)執(zhí)行的!!
4.6.??After最終通知使用
無論目標(biāo)方法是否出現(xiàn)異常,都將執(zhí)行增強(qiáng)代碼?
場(chǎng)景:?釋放資源?
try?{
??開啟事務(wù)…
??執(zhí)行代碼
}?catch?{
???事務(wù)回滾
}?finally?{
???事務(wù)提交
}
第一步:?編寫增強(qiáng)方法?
?
?
第二步:?配置切入點(diǎn)和切面?
?
?
小結(jié):?Around環(huán)繞通知什么都可以?
try{
前置通知…?
執(zhí)行目標(biāo)方法
后置通知…
}catch?{
異常通知…
}finally?{
最終通知…
}
5.??AspectJ?AOP?切面編程?(注解配置?)
新建?spring3_day3_annotation?web?項(xiàng)目,?導(dǎo)入spring?AOP開發(fā)jar包?
5.1.??編寫目標(biāo)業(yè)務(wù)類?
?
配置applicationContext.xml?bean的掃描?
?
5.2.??編寫Advice增強(qiáng)?
配置applicationContext.xml?
?
使用注解修飾Advice類?
@Aspect?這是一個(gè)切面?
@Before?前置通知
@AfterReturning?后置通知
@Around?環(huán)繞通知
@AfterThrowing?拋出通知?
@After最終通知?
@Pointcut?切入點(diǎn)?
?
?
?
?
?
?
小結(jié):?
1、?注冊(cè)Bean??<context:component-scan>?(@Service、@Controller、?@Repository?、@Component?)
2、?聲明具有增強(qiáng)方法類是一個(gè)切面?@Aspect?
3、?在對(duì)應(yīng)方法上,聲明各種通知?@Before?@AfterReturning?@Around?@AfterThrowing?@After?
4、?根據(jù)切面注解自動(dòng)生成代理?<aop:aspectj-autoproxy??/>
5.3.??使用@Pointcut?定義切入點(diǎn)?
?
將公共切入點(diǎn)表達(dá)式,抽取出來,便于后期維護(hù)?
Spring規(guī)定,將@Pointcut注解加到?私有、無返回值、無參數(shù)的方法上?(該方法的名字?就是切入點(diǎn)的名字?!)
?
如果引用切入點(diǎn),類似方法調(diào)用?
?
?
能否在一個(gè)通知上,?應(yīng)用多個(gè)切入點(diǎn)?可以?&&?或者?||?引入多個(gè)?
pointcut1()?&&?pointcut2()?,?必須同時(shí)滿足?pointcut1和pointcut2?切入點(diǎn)表達(dá)式?
pointcut1()||pointcut2()?只需要滿足?pointcut1?或者?pointcut2?當(dāng)中一個(gè)切入點(diǎn)表達(dá)式?
?
?
6.??Spring?JdbcTemplate?
?學(xué)習(xí)spring?重點(diǎn)三---?六章?
第三章:核心技術(shù):?IoC和AOP?
第四章:數(shù)據(jù)訪問:?(JDBC數(shù)據(jù)訪問?JdbcTemplate?、?事務(wù)管理?、?整合ORM框架?)
第五章:Web應(yīng)用?:SpringMVC?---?后續(xù)課程?
第六章:整合?
?
6.1.??JdbcTemplate?快速入門?
?
JdbcTemplate?用來簡化JDBC?編程開發(fā),使用效果類似?DbUtils?框架?
?
第一步:?新建web項(xiàng)目?spring3_day2_jdbctemplate?,導(dǎo)入jar包?
4個(gè)核心
2個(gè)日志
1個(gè)web集成
1個(gè)junit集成
1個(gè)inject?
4個(gè)AOP?
?
導(dǎo)入?jdbc和tx?2個(gè)jar包?
導(dǎo)入?oracle驅(qū)動(dòng)?
?
?
第二步:?編寫無配置文件Jdbc程序?
--?Create?the?user?
create?user?SH1026
??identified?by?""
??default?tablespace?SYSTEM
??temporary?tablespace?TEMP
??profile?DEFAULT;
--?Grant/Revoke?role?privileges?
grant?connect?to?SH1026;
grant?resource?to?SH1026;
--?Grant/Revoke?system?privileges?
grant?unlimited?tablespace?to?SH1026;
?
?
6.2.??使用spring配置管理JdbcTemplate?
在applicationContext.xml?配置數(shù)據(jù)庫連接池和JdbcTemplate?
?
6.2.1.??DrvierManagerDataSource?配置
?
測(cè)試
?
6.2.2.??DBCP?連接池BasicDataSource?配置?
導(dǎo)入?dbcp?和pool的jar包?
?
配置?
?
?
6.2.3.??C3P0連接池?CombopooledDataSource?使用
導(dǎo)入c3p0的jar包?
?
配置
?
6.2.4.??JNDI數(shù)據(jù)庫配置使用?
什么是JNDI???
JNDI(Java?Naming?and?Directory?Interface,Java命名和目錄接口)?
在JNDI容器進(jìn)行配置,將對(duì)象交給容器創(chuàng)建和管理,為對(duì)象進(jìn)行命名?,在JNDI容器其它程序通過名字去訪問這個(gè)對(duì)象。?
?
第一步:?在tomcat配置數(shù)據(jù)庫連接池?
需要在<Context>元素下配置?<Resouce>?元素?
配置位置?:?server.xml?、context.xml?(所有項(xiàng)目生效)、?項(xiàng)目目錄?WebRoot/META-INF?(只對(duì)當(dāng)前項(xiàng)目有效?)?
?
在項(xiàng)目WebRoot/META-INF?新建context.xml??
?
將數(shù)據(jù)庫驅(qū)動(dòng)包,復(fù)制tomcat/lib下?
?
?
第二步:?spring訪問?配置JNDI?
?
配置applicationContext.xml?
?
?
編寫Servlet?,從Spring獲取對(duì)象?
?
6.3.??外部屬性文件的配置使用?
什么是外部屬性文件??
屬性文件?---?properties文件?
?
XML中很多內(nèi)容,格式比properties?復(fù)雜,?將經(jīng)常需要改動(dòng)屬性數(shù)據(jù),配置properties文件,?便于后期維護(hù)!?
?
?
在applicationContext.xml?引入屬性文件,通過${}?引入屬性值?
?
?
6.4.??編寫DAO程序,實(shí)現(xiàn)數(shù)據(jù)表CRUD操作?
6.4.1.??建立數(shù)據(jù)表,編寫實(shí)體類
建立customers數(shù)據(jù)表?
--?Create?table
create?table?customers
(
??id???number,
??name?varchar2(50),
??city?varchar2(100),
??age??number
)
;
--?Create/Recreate?primary,?unique?and?foreign?key?constraints?
alter?table?customers
??add?constraint?customers_pk?primary?key?(ID);
?
實(shí)體類
?
6.4.2.??在DAO中注入JdbcTemplate?
?
?
?
配置?
?
6.4.3.??通過update方法,實(shí)現(xiàn)增加、修改、刪除?
JdbcTemplate提供?
?
?
?
?
?
?
6.4.4.??通過queryXxx方法實(shí)現(xiàn)查詢?
l?返回簡單類型數(shù)據(jù)
返回int?:?queryForInt
返回long:?queryForLong
返回String?:?queryForObject(sql,?requiredType,?args?)?requiredType就是返回類型?
?
?
l?返回復(fù)雜類型數(shù)據(jù):?
需要使用RowMapper對(duì)象?
什么是RowMapper????將每行數(shù)據(jù)封裝為Customer對(duì)象?
?
?
?
?
問題:?如果表中列非常多,?自定義RowMapper?非常復(fù)雜?
類屬性名和表列名,代碼能否優(yōu)化?!
?
Spring?JdbcTemplate?提供ParameterizedBeanPropertyRowMapper?,自動(dòng)完成同名列和屬性?自動(dòng)對(duì)應(yīng)封裝?!
?
?
今天總結(jié):?
1、?IoC和DI的概念和區(qū)別??IoC是如何實(shí)現(xiàn)的??
2、?什么AOP??如何實(shí)現(xiàn)的??在項(xiàng)目哪些功能中使用到AOP??
3、?BeanFactory和FactoryBean的區(qū)別??
4、?singleton和prototype的區(qū)別???能否寫出單例設(shè)計(jì)模式代碼實(shí)現(xiàn)??
5、?BeanPostProcessor?后處理的作用??
6、?如何用xml和注解?定義Bean??如何完成屬性注入???
7、?Spring?AOP?使用什么技術(shù)實(shí)現(xiàn)的???底層技術(shù)?JDK和Cglib動(dòng)態(tài)代理?
8、?傳統(tǒng)Spring?AOP?開發(fā)和配置?
9、?重點(diǎn)掌握?AspectJ?AOP?開發(fā)和配置?(XML和注解,重點(diǎn)掌握一種?)
10、?advisor、advice、aspect?區(qū)別
11、?SpringAOP?應(yīng)用:?運(yùn)行時(shí)間、?權(quán)限控制、?緩存、事務(wù)管理??…?
12、?數(shù)據(jù)源配置?JNDI?和?C3p0?重點(diǎn)?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/wangchuanfu/p/5658332.html
總結(jié)
以上是生活随笔為你收集整理的SpringTest2的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu14.04安装pip及配置
- 下一篇: PAT-乙级-1020. 月饼 (25)