Spring學(xué)習(xí)筆記之AOP

引言:AOP全稱為Aspect Oriented Programming即為面向面變成向胡,它是一種變成思想;Spring為了管理日志信息惊完,事務(wù)信息以及異常等信息將這種思想加入到了自己的架構(gòu)中僵芹;我們稱之為SpringAOP;
一:究竟什么是面向切面編程专执?
百度百科:通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)淮捆。AOP是OOP的延續(xù);是軟件開發(fā)中的一個熱點本股,也是Spring框架中的一個重要內(nèi)容攀痊,是函數(shù)式編程的一種衍生范型。利用AOP可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離拄显,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低苟径,提高程序的可重用性,同時提高了開發(fā)的效率躬审。
引用知乎上一人回答:就是在程序執(zhí)行過程中動態(tài)地將代碼切入到類的指定方法或者指定位置上的編程思想棘街;
二:怎么使用?
在java的Spring框架中具體有兩種實現(xiàn)方法承边,一種是通過JDK的動態(tài)代理實現(xiàn)遭殉,一種是通過Cglib的動態(tài)代理實現(xiàn);
1:早期的Aop:
A:通過JDK的動態(tài)代理實現(xiàn):
a:需要接口b:實現(xiàn)類(代理類)c:織入類d:代理類

//接口類
package com.cp.insist.dao;
import com.cp.insist.entity.User;
public interface InteUserDao {
    public  void updateUser(Integer id ,User user);
}
//實現(xiàn)類
public class userDao implements InteUserDao{

    @Override
    public void updateUser(Integer id,User user) {
        System.out.println("更新用戶的id為:"+id+"用戶為"+user);
    }
}
package com.cp.insist.dao;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * java動態(tài)代理類必須要有一個接口
這是一個織入類
 * @author 陳鵬
 *
 */
public class UserHander implements InvocationHandler{
    private Object target;
    /**
     * 
    * @Description:通過構(gòu)造方法去傳遞目標(biāo)對象
    * @創(chuàng)建時間 2016年7月18日
    * @創(chuàng)建人 陳鵬
    * @throws
     */
    public UserHander(Object source){
        this.target=source;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("開始提交事務(wù)了博助。险污。。");
              // 執(zhí)行代理的方法
        Object object = method.invoke(target, args);
        System.out.println("提交事務(wù)成功了8辉馈;着础!");
        return object;
    }

}
/測試類
package com.cp.insist.test;
import java.lang.reflect.Proxy;
import com.cp.insist.dao.InteUserDao;
import com.cp.insist.dao.UserHander;
import com.cp.insist.dao.userDao;
public class MainTest {
    public static void main(String[] args) {
       1:闖將一個實現(xiàn)類窖式,被代理的對象 
        IUserDao userDao = new UserDaoImpl();
        2:動態(tài)處理對象
        UserHandler userHandler = new UserHandler(userDao);
        3:創(chuàng)建一個代理對象
        IUserDao proxy = (IUserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), 
                userDao.getClass().getInterfaces(), 
                userHandler);
        proxy.saveUser(new User());

    }
}

使用cglib來進(jìn)行Aop的動態(tài)代理的處理蚁飒,簡化了jdk的Aop動態(tài)代理的處理
不需要使用接口;
代理類的對象本身并不真正實現(xiàn)服務(wù)萝喘,而是通過調(diào)用委托類的對象的相關(guān)方法淮逻,來提供特定的服務(wù)。
1:建一個dao類阁簸,再建一個動態(tài)的處理類實現(xiàn)MethodInterceptor類弦蹂;
2:并且重寫里面的方法,再調(diào)用ivoinvokeSuper方法

//被代理類
public class userDao {
    public void saveUser(User user){
        System.out.println("進(jìn)入了user的保存方法");
    }
}
//織入類
public class userProxy implements MethodInterceptor{
        //增強(qiáng)對象
    private Enhancer enhancer = new Enhancer();
    public Object getProxyObject(Class clz){
        enhancer.setSuperclass(clz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object arg0, Method method, Object[] arrO,
            MethodProxy proxy) throws Throwable {
        System.out.println("這里提交事務(wù)G拷选凸椿!");
                //調(diào)用方法
        Object obj = proxy.invokeSuper(arg0, arrO);
        System.out.println("主要業(yè)務(wù)");
        return obj;
    }
}
測試類:
public class Test {
    public static void main(String[] args) {
        userProxy proxy = new userProxy();
        userDao user = (userDao)proxy.getProxyObject(userDao.class);
        user.saveUser(new User());
    }
}

2:引入注解之后的Aop
同樣也分jdk的動態(tài)代理和cglib的動態(tài)代理
這里我們只將jdk的動態(tài)代理

//接口
public interface Iuser {
    public void say(String name) throws SQLException;
}
//實現(xiàn)類
public class UserImp implements Iuser{

    @Override
    public void say(String name) throws SQLException {
            System.out.println("我是一個"+name+"通知"+"目的方法");
            throw new SQLException("對不起查詢失敗");
    }
}
//通知類:這是一個后置通知
public class adviceAfter implements AfterReturningAdvice{
    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2,
            Object arg3) throws Throwable {
        System.out.println("我是一個后置通知");
    }
}
//配置文件:因為我們采用的注解方式:利用IOC思想;讓容器去替我們管理對象翅溺,所以在相應(yīng)的配置文件我們需要:
<property name="optimize" value="false"></property>通過設(shè)置它的值我們可以選擇使用jdk的動態(tài)代理還是cglib的動態(tài)代理脑漫;默認(rèn)為false髓抑,采用jdk的動態(tài)代理
                <!--通知類-->
        <bean id="advice2" class="com.chenpeng.dao2.MethodInterceptorAdvice"></bean>
               <!--實現(xiàn)類-->
        <bean id ="userimp" class="com.chenpeng.dao2.UserImp"></bean>
                <!--根據(jù)通知類和實現(xiàn)類去獲取代理對像-->
        <bean id="factory" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="userimp"></property>
            <property name="interfaces" value="com.chenpeng.dao2.Iuser"></property>
            <!-- 第一種方法:多個通知時 -->
            <!-- <property name="interceptorNames" value="advice,advice1,advice2,exception"></property> -->
            <!-- 第二種方法:多個通知時 -->
            <!-- <property name="interceptorNames">
                <list>
                    <value>advice</value>
                    <value>advice1</value>
                    <value>advice2</value>
                    <value>exception</value>
                </list>
            </property> -->
            <!-- 第三種方法:多個通知時 -->
            <property name="interceptorNames">
                <list>
                    <idref bean="advice"/>
                    <idref bean="advice1"></idref>
                    <idref bean="advice2"></idref>
                    <idref bean="exception"></idref>
                </list>
            </property>
        </bean>
//測試類
public class test2 {
    public static void main(String[] args) {
        ApplicationContext content = new ClassPathXmlApplicationContext("classpath:com/chenpeng/dao2/bean.xml");
                //jdk動態(tài)代理使用接口轉(zhuǎn)型;cjlib的動態(tài)代理使用具體類轉(zhuǎn)型
        Iuser user = (com.chenpeng.dao2.Iuser)content.getBean("factory");
        user.say("前置");
    }
}

3:最新的AOP使用Aspectj將切面和植入類進(jìn)行完美結(jié)合省去很多代碼

接口類
public interface Iuser {
    public void addUser();
    public void addUser1();
    public void updateUser();
    public void updateUser(int a);
}
實現(xiàn)類:
@Component
public class cpUserImp implements Iuser{
    @Override
    public void addUser() {
        System.out.println("我是一個addUser的方法");
    }
    @Override
    public void updateUser() {
        System.out.println("我是一個updateUser的方法");
    }
    @Override
    public void addUser1() {
        // TODO Auto-generated method stub
        System.out.println("我是一個addUser1的方法");
    }

    @Override
    public void updateUser(int a) {
        // TODO Auto-generated method stub
        System.out.println("我是一個帶參數(shù)的update方法");
    }
}
織入類+切面
@Component
@Aspect
public class aspectAdvitor {
    @Before("execution(* add*(..))")//攔截指定的方法
    public void say(){
        System.out.println("我是一個aspectj版本的aop的方法");
    }
    @AfterReturning("execution(* update*(..))&&args(int,..)")
    public void work(){
        System.out.println("我是一個update的work后置通知方法");
    }
    //環(huán)繞型通知
    @Around("execution(* update*(..))")
    public void round(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("事務(wù)開始");
        joinPoint.proceed();
        System.out.println("事務(wù)提交");
    }
}
關(guān)于配置文件:由于我們采用了注解
第一種方式:
<!-- 表示開啟了Aspect模式的Aop -->
        <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
        <!--切面+織入類-->
    <bean  class="com.chenpeng.dao4.AspectAop"></bean>
        <!--具體類-->
      <bean id="user" class="com.chenpeng.dao4.UserImp"></bean>
第二種方式:
<!--掃包:將所有添加注解的類相關(guān)對象都進(jìn)行實例化-->
<context:component-scan base-package="com.chenpeng.dao4.**"></context:component-scan>
<!-- 表示開啟了Aspect模式的Aop -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
第四種方式:主體的類文件和第三種一樣优幸,我們可以將具體的切入點在配置文件書寫吨拍;更加方便:
<context:component-scan base-package="com.chenpeng.dao6"></context:component-scan>
    <aop:config>
        <!-- 可以將切點單獨定義出來 -->
        <aop:pointcut expression="execution(* update*(..))" id="roundAdvisor"/>
              <!---ref="aspectAdvitor"-這個就是我們定義的切面和通知類由于掃包了,默認(rèn)的bean的id就是類名首字母小寫->
        <aop:aspect ref="aspectAdvitor">
                        <!--切面類以及執(zhí)行的方法-->
            <aop:after method="say" pointcut="execution(* add*(..))"/>
            <!-- 引用上面定義的切點 -->
            <aop:around method="round" pointcut-ref="roundAdvisor"/>
        </aop:aspect>
    </aop:config>

以上就是自己學(xué)習(xí)spring中的AOP的相關(guān)筆記网杆;如果有不對的地方還望大家及時指點羹饰;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碳却,隨后出現(xiàn)的幾起案子队秩,更是在濱河造成了極大的恐慌,老刑警劉巖昼浦,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馍资,死亡現(xiàn)場離奇詭異,居然都是意外死亡关噪,警方通過查閱死者的電腦和手機(jī)鸟蟹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來使兔,“玉大人建钥,你說我怎么就攤上這事∨傲ぃ” “怎么了熊经?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長置蜀。 經(jīng)常有香客問我,道長悉盆,這世上最難降的妖魔是什么盯荤? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮焕盟,結(jié)果婚禮上秋秤,老公的妹妹穿的比我還像新娘。我一直安慰自己脚翘,他們只是感情好灼卢,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著来农,像睡著了一般鞋真。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沃于,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天涩咖,我揣著相機(jī)與錄音海诲,去河邊找鬼。 笑死檩互,一個胖子當(dāng)著我的面吹牛特幔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播闸昨,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蚯斯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了饵较?” 一聲冷哼從身側(cè)響起拍嵌,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎告抄,沒想到半個月后撰茎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡打洼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年龄糊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片募疮。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡炫惩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阿浓,到底是詐尸還是另有隱情他嚷,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布芭毙,位于F島的核電站筋蓖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏退敦。R本人自食惡果不足惜粘咖,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侈百。 院中可真熱鬧瓮下,春花似錦、人聲如沸钝域。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽例证。三九已至路呜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拣宰。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工党涕, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人巡社。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓膛堤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親晌该。 傳聞我的和親對象是個殘疾皇子肥荔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)朝群,斷路器燕耿,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • 一> 代理模式 概述 代理(Proxy)是一種設(shè)計模式, 提供了對目標(biāo)對象另外的訪問方式姜胖;即通過代理訪問目標(biāo)對象誉帅。...
    奮斗的老王閱讀 1,104評論 0 50
  • 什么是Spring Spring是一個開源的Java EE開發(fā)框架。Spring框架的核心功能可以應(yīng)用在任何Jav...
    jemmm閱讀 16,445評論 1 133
  • AOP核心概念 橫切關(guān)注點:對哪些方法進(jìn)行攔截右莱,攔截后怎么處理蚜锨,這些關(guān)注點稱之為橫切關(guān)注點切面(aspect):類...
    lijiaccy閱讀 325評論 0 0