spring 入门实战(四) Aop

10 篇文章 0 订阅

spring aop实战

本篇只是用实际案例帮助快速入门,不涉及具体概念

1.0 开发环境
 1.0 开发工具 eclipse
 2.0 jar包  除了Spring jar包外,还需要其他jar包  spring本身并没有提供  我也不知为什么
 https://pan.baidu.com/s/16MTV5K8zG8m9cROC-6G_iQ  提取码:hro2
2.0 搭建主业务模块 Affairs.java
package com.ccut.aop;

import java.io.IOException;

public class Affairs {

    private String message1;
    private String message2;


    public Affairs(){}


    public String getMessage1() {
        return message1;
    }

    public void setMessage1(String message1) {
        this.message1 = message1;
    }

    public String getMessage2() {
        return message2;
    }

    public void setMessage2(String message2) {
        this.message2 = message2;
    }

    public void PersonA(){
        System.out.println("A 这个人说啊:"+this.getMessage1());
    }

    public void PersonB(){
        System.out.println("B 这个人说啊:"+this.getMessage2());
    }


    public void error(){
        System.out.println("error!!!");
        int i = 10;
        if(i != 1){
            throw new IllegalArgumentException("这是参数异常");
        }

    }



}

3.0 搭建切面功能类Function
package com.ccut.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class Function {
        private String fmessage;
        private String mmessage;
        public Function(){}
        public String getFmessage() {
            return fmessage;
        }
        public void setFmessage(String fmessage) {
            this.fmessage = fmessage;
        }
        public String getMmessage() {
            return mmessage;
        }
        public void setMmessage(String mmessage) {
            this.mmessage = mmessage;
        }

        public void f(){
            System.out.println(this.getFmessage());
        }

        public void around(ProceedingJoinPoint pj){
            System.out.println("在目标函数之前执行");
            try {
                pj.proceed();
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                System.out.println("在目标函数之后执行");
            }
        }

        public void m(){
            System.out.println(this.getMmessage());
        }

        public void mess(String msg){
            System.out.println(msg+"  这是返回后的信息");
        }

        public void err(Throwable ex){
            System.out.println("这个错误是:"+ex);
        }

}
4.0 搭建测试类 Test.java
package com.ccut.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ccut.aop.Affairs;

public class Test {
    public static void main(String[] args) {

        ApplicationContext applicationContext = 
        new ClassPathXmlApplicationContext("./resources/aop.xml");

        Affairs affairs = (Affairs) applicationContext.getBean("affairs");
        affairs.PersonA();
        affairs.PersonB();

    }
}

上面是公共的,也就是说下面的测试都用的是上面的代码


5.0 编写配置文件aop.xml 位于resources文件夹内(这是整合后的,单个功能的配置文件在后面 暂时不用看这个)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <aop:config>
        <aop:aspect id="aspect1" ref="function">
            <aop:pointcut id="personA" expression="execution(* com.ccut.aop.Affairs.PersonA())"/> 
            <aop:pointcut id="personB" expression="execution(* com.ccut.aop.Affairs.PersonB())"/>           
            <!-- <aop:pointcut id="return" expression="execution(* com.ccut.aop.Affairs.*(..))"/>           
            <aop:before pointcut-ref="personA" method="f"/>
            <aop:after method="m" pointcut-ref="personA"/>
            <aop:after-returning method="mess" returning="msg" pointcut-ref="return"/> -->
            <aop:around method="around" pointcut-ref="personB"/>
        </aop:aspect>
    </aop:config>

    <bean id="affairs" class = "com.ccut.aop.Affairs">
        <property name="message1" value="我就是 A 啊  这有什么疑问吗?"/>
        <property name="message2" value="我就是 B 啊  这有什么疑问吗?"/>
    </bean>

    <bean id = "function" class="com.ccut.aop.Function">
        <property name="fmessage" value="我可能在你前面执行!"></property>
        <property name="mmessage" value="我可能在你后面执行呢!"></property>
    </bean>



    </beans>
5.1 我们把上面的配置文件拆开看,以便更好的理解

aop的切入形式有一下几种

<aop:before  method= ''beforemethod'',pointcut-ref="cut1"/>
<aop:after  method= ''aftermethod'',pointcut-ref="cut2"/>
<aop:after-returning method="mess" returning="msg" pointcut-ref="return"/>
<aop:around method="around" pointcut-ref="personB"/>
<aop:after-throwing method="" pointcut-ref="" throwing=""/>
<aop:declare-parents/>这个暂时不解释
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <bean id="affairs" class = "com.ccut.aop.Affairs">
        <property name="message1" value="我就是 A 啊  这有什么疑问吗?"/>
        <property name="message2" value="我就是 B 啊  这有什么疑问吗?"/>
    </bean>

    <bean id = "function" class="com.ccut.aop.Function">
        <property name="fmessage" value="我可能在你前面执行!"></property>
        <property name="mmessage" value="我可能在你后面执行呢!"></property>
    </bean>

    </beans>

上面的简化后的配置文件实现了对事物类 和切面类相关参数的注入
执行简化后的配置文件的结果为:
这里写图片描述

5.2.1 下面是把功能类的某一方法切入到切入点前面执行的aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <aop:config>
        <aop:aspect id="aspect1" ref="function">

            <aop:pointcut id="personA" expression="execution(* com.ccut.aop.Affairs.PersonA())"/>   
            <!-- 下面是以后要改动的代码↓↓↓↓↓↓↓↓-->         
            <aop:before pointcut-ref="personA" method="f"/>
            <-- 上面是以后要改动的代码↑↑↑↑↑↑↑-->
        </aop:aspect>
    </aop:config>

    <bean id="affairs" class = "com.ccut.aop.Affairs">
        <property name="message1" value="我就是 A 啊  这有什么疑问吗?"/>
        <property name="message2" value="我就是 B 啊  这有什么疑问吗?"/>
    </bean>

    <bean id = "function" class="com.ccut.aop.Function">
        <property name="fmessage" value="我可能在你前面执行!"></property>
        <property name="mmessage" value="我可能在你后面执行呢!"></property>
    </bean>

    </beans>

执行结果:
这里写图片描述

5.2.2 把指定方法放在切入点后面执行

配置文件对应位置改为

<aop:after method="m" pointcut-ref="personA"/>

结果为:
这里写图片描述

5.2.3 在指定方法结束时候执行

配置文件如下

<aop:config>
        <aop:aspect id="aspect1" ref="function">        
            <aop:pointcut id="return" expression="execution(* com.ccut.aop.Affairs.*(..))"/>        

        <aop:after-returning method="mess" returning="msg" pointcut-ref="return"/>

        </aop:aspect>
    </aop:config>

测试类:

package com.ccut.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ccut.aop.Affairs;

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("./resources/aop.xml");

        Affairs affairs = (Affairs) applicationContext.getBean("affairs");
        affairs.PersonA();
        affairs.PersonB();

        affairs.getMessage1();


    }
}

结果:
这里写图片描述

5.2.4 抛出异常后执行 aop:after-throwing 这个方法不能完全处理异常 最终还是会交给jvm

配置文件:
把上面的 < aop:after-returning method=”mess” returning=”msg” pointcut-ref=”return”/> 替换为下面的

     <aop:after-throwing method="err" throwing="ex" pointcut-ref="return"/>

主方法中的affairs.getMessage1();改为下面

affairs.error();

结果:
这里写图片描述

5.2.5 环绕通知增强 aop:around

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <aop:config>
        <aop:aspect id="aspect1" ref="function">

            <aop:pointcut id="personB" expression="execution(* com.ccut.aop.Affairs.PersonB())"/>           
            <aop:around method="around" pointcut-ref="personB"/>
        </aop:aspect>
    </aop:config>

    <bean id="affairs" class = "com.ccut.aop.Affairs">
        <property name="message1" value="我就是 A 啊  这有什么疑问吗?"/>
        <property name="message2" value="我就是 B 啊  这有什么疑问吗?"/>
    </bean>

    <bean id = "function" class="com.ccut.aop.Function">
        <property name="fmessage" value="我可能在你前面执行!"></property>
        <property name="mmessage" value="我可能在你后面执行呢!"></property>
    </bean>



    </beans>

测试类:

package com.ccut.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ccut.aop.Affairs;

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("./resources/aop.xml");

        Affairs affairs = (Affairs) applicationContext.getBean("affairs");
        affairs.PersonA();
        affairs.PersonB();
    }
}

结果:
这里写图片描述

这里注意 环绕通知方法重点一定要有下面这个形参ProceedingJoinPoint pj 如果没有 pj.proceed();这个代码
则被切入的函数不会执行

 public void around(ProceedingJoinPoint pj){
            System.out.println("在目标函数之前执行");
            try {
                pj.proceed();
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                System.out.println("在目标函数之后执行");
            }
        }

这里的< aop:declare-parents/>这个暂时不解释

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值