我的spring之旅之AOP编程

AOP介绍

aop( aspect oriented programming ) 面向切面(方面)编程,是对所有对象或者是一类对象编程,核心是( 在不增加代码的基础上, 还增加新功能 ),也是spring的核心技术之一。

AOP术语

1.切面(aspect):要实现的交叉功能,是系统模块化的一个切面或领域。如日志记录。
2.连接点:应用程序执行过程中插入切面的地点,可以是方法调用,异常抛出,或者要修改的
字段。
3.通知:切面的实际实现,他通知系统新的行为。如在日志通知包含了实
现日志功能的代码,如向日志文件写日志。通知在连接点插入到应用系统中。
4.切入点:定义了通知应该应用在哪些连接点,通知可以应用到AOP框架支持的任何连接点。
5.引入:为类添加新方法和属性。
6.目标对象:被通知的对象。既可以是你编写的类也可以是第三方类。
7.代理:将通知应用到目标对象后创建的对象,应用系统的其他部分不用为了支持代理对象而
改变。
8.织入:将切面应用到目标对象从而创建一个新代理对象的过程。织入发生在目标
对象生命周期的多个点上:
编译期:切面在目标对象编译时织入.这需要一个特殊的编译器.
类装载期:切面在目标对象被载入JVM时织入.这需要一个特殊的类载入器.
运行期:切面在应用系统运行时织入.

sp18

通知种类

sp19

快速入门

step

1、新建一个接口TestServiceInter

public interface TestServiceInter {

    public void sayHello();
}

2、新建一个目标对象Test1Service类,并实现TestServiceInter接口


public class Test1Service implements TestServiceInter {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("hi "+name);
    }
}

3、前置MethodBeforeAdvice使用


public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

    /**
     * method: 被调用方法名字
     * args: 给method传递的参数
     * target: 目标对象
     */
    public void before(Method method, Object[] args, Object target)
            throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("记录日志..."+"方法名称:"+method.getName()+" 目标对象:"+target);

    }

}

4、配置bean
4-1、配置被代理的对象

<bean id="test1Service" class="com.ydc.aop.Test1Service">
        <property name="name" value="ydc" />
    </bean>

4-2、配置MethodBeforeAdvice通知

<bean id="MyMethodBeforeAdvice" class="com.ydc.aop.MyMethodBeforeAdvice" />

4-3、配置代理对象

<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.ydc.aop.TestServiceInter</value>
            </list>
        </property>
        <!-- 把通知织入到代理对象 -->
        <property name="interceptorNames">
            <!-- 相当于包MyMethodBeforeAdvice前置通知和代理对象关联,我们也 可以把通知看出拦截器,struts2核心拦截器 -->
            <value>MyMethodBeforeAdvice</value>
        </property>
        <!-- 配置被代理对象,可以指定 -->
        <property name="target" ref="test1Service" />
    </bean>

5、运行测试

sp20

看见没,MethodBeforeAdvice的作用就是在目标对象(Test1Service)调用sayHello()方法前先调起MethodBeforeAdvice的before函数,但该函数并没有在任何地方显示调用,并且该方法可以获取到目标对象(Test1Service)的好多信息,这样一来,可在目标对象的方法调用之前可以做一些事情,比如写入日志。

6、让目标对象再实现TestServiceInter2接口


public interface TestServiceInter2 {

    public void sayBye();
}

public class Test1Service implements TestServiceInter,TestServiceInter2 {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("hi "+name);
    }

    public void sayBye() {
        // TODO Auto-generated method stub
        System.out.println("bye "+name);
    }

}

7、增加代理接口

<!-- 配置代理对象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.ydc.aop.TestServiceInter</value>
                <value>com.ydc.aop.TestServiceInter2</value>
            </list>
        </property>
        <!-- 把通知织入到代理对象 -->
        <property name="interceptorNames">
            <!-- 相当于包MyMethodBeforeAdvice前置通知和代理对象关联,我们也 可以把通知看出拦截器,struts2核心拦截器 -->
            <value>MyMethodBeforeAdvice</value>
        </property>
        <!-- 配置被代理对象,可以指定 -->
        <property name="target" ref="test1Service" />
    </bean>

8、测试运行

sp21

看见没,可以在多个点切入。

AOP基本原理

sp22

9、AfterReturningAdvice后置通知

9-1、新建后置通知


public class MyAfterReturningAdvice implements AfterReturningAdvice{

    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        // TODO Auto-generated method stub

        System.out.println("执行完"+arg1.getName()+"之后关闭资源");

    }

}

9-2、配置后置通知

<bean id="MyAfterReturningAdvice" class="com.ydc.aop.MyAfterReturningAdvice" />

9-3、把后置通知织入到代理对象

<property name="interceptorNames">
            <!-- 相当于包MyMethodBeforeAdvice前置通知和代理对象关联,我们也 可以把通知看出拦截器,struts2核心拦截器 -->
            <list>
                <value>MyMethodBeforeAdvice</value>
                <value>MyAfterReturningAdvice</value>
            </list>

        </property>

10、再次运行我们的程序

sp23

看见没,我们可以使用后置通知AfterReturningAdvice在目标对象执行完某一个函数之后做一下业务。

11、MethodInterceptor 通知的使用

11-1、新建MethodInterceptor通知


public class MyAroundAdvice implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {

        System.out.println("调用方法前:");

        Object object=arg0.proceed();

        System.out.println("调用方法后:");

        return object;
    }

}

11-2、配置MethodInterceptor通知

<bean id="MyAroundAdvice" class="com.ydc.aop.MyAroundAdvice" />

11-3、把MethodInterceptor通知织入到代理对象

<!-- 把通知织入到代理对象 -->
        <property name="interceptorNames">
            <!-- 相当于包MyMethodBeforeAdvice前置通知和代理对象关联,我们也 可以把通知看出拦截器,struts2核心拦截器 -->
            <list>
                <value>MyMethodBeforeAdvice</value>
                <value>MyAfterReturningAdvice</value>
                <value>MyAroundAdvice</value>
            </list>

        </property>

12、测试运行

sp24

看见没有,其实MethodInterceptor通知的作用=MethodBeforeAdvice作用+AfterReturningAdvice作用。

13、ThrowsAdvice 通知的使用

13-1、新建异常通知

package com.ydc.aop;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;


public class MyThrowsAdvice implements ThrowsAdvice {


    public void afterThrowing(Method m, Object[] os, Object target, Exception e) {

        System.out.println("出大事了"+e.getMessage());
    }
}

13-2、配置ThrowsAdvice通知

<bean id="MyThrowsAdvice" class="com.ydc.aop.MyThrowsAdvice" />

13-3、把ThrowsAdvice通知织入到代理对象

<!-- 把通知织入到代理对象 -->
        <property name="interceptorNames">
            <!-- 相当于包MyMethodBeforeAdvice前置通知和代理对象关联,我们也 可以把通知看出拦截器,struts2核心拦截器 -->
            <list>
                <value>MyMethodBeforeAdvice</value>
                <value>MyAfterReturningAdvice</value>
                <value>MyAroundAdvice</value>
                <value>MyThrowsAdvice</value>
            </list>

        </property>

14、测试运行

sp25

看见没,ThrowsAdvice通知主要是在抛出异常的地面切入,这样一来可以统计项目的异常崩溃信息,非常有价值。

15、bean的完整配置

<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <!-- 配置被代理的对象 -->
    <bean id="test1Service" class="com.ydc.aop.Test1Service">
        <property name="name" value="ydc" />
    </bean>

    <bean id="MyMethodBeforeAdvice" class="com.ydc.aop.MyMethodBeforeAdvice" />
    <bean id="MyAfterReturningAdvice" class="com.ydc.aop.MyAfterReturningAdvice" />
    <bean id="MyAroundAdvice" class="com.ydc.aop.MyAroundAdvice" />
    <bean id="MyThrowsAdvice" class="com.ydc.aop.MyThrowsAdvice" />
    <!-- 配置代理对象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.ydc.aop.TestServiceInter</value>
                <value>com.ydc.aop.TestServiceInter2</value>
            </list>
        </property>
        <!-- 把通知织入到代理对象 -->
        <property name="interceptorNames">
            <!-- 相当于包MyMethodBeforeAdvice前置通知和代理对象关联,我们也 可以把通知看出拦截器,struts2核心拦截器 -->
            <list>
                <value>MyMethodBeforeAdvice</value>
                <value>MyAfterReturningAdvice</value>
                <value>MyAroundAdvice</value>
                <value>MyThrowsAdvice</value>
            </list>

        </property>
        <!-- 配置被代理对象,可以指定 -->
        <property name="target" ref="test1Service" />
    </bean>
</beans>
发布了53 篇原创文章 · 获赞 58 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/XiNanHeiShao/article/details/76039097
今日推荐