面向切面编程(三)

本方法与面向切面编程(一)和(二)的实现结果是一样的,但是实现方法不一样。

再介绍一遍spring AOP中的专业术语(其中连接点、切入点、切面很重要):

       1.通知(Advice):通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。
       2.连接点(Joinpoint):程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。
       3.切入点(Pointcut):通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,spring中允许我们方便的用正则表达式来指定
       4.切面(Aspect):
通知和切入点共同组成了切面:时间、地点和要发生的“故事”
       
5.引入(Introduction):引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)
       
6.目标(Target):即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事)
       
7.代理(proxy):应用通知的对象,详细内容参见设计模式里面的代理模式
       
8.织入(Weaving):把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:

(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器
(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码
(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

示例代码:

BizImpl.java(实现类的接口):

    /*
     * 时间:2016年9月28日20:41:10
     * 程序功能:实现类的接口
     * */
    package com.sc.biz;
    public interface BizImpl {

        public void buy(String username,String bookname,double price);

        public void pinlun(String username,String pinlunleirong);

    }

BookBizImpl.java(实现类):

    /*
     * 时间:2016年9月28日20:41:35
     * 程序功能:实现类,继承接口并实现方法
     * */
    package com.sc.biz;
    public class BookBizImpl implements BizImpl {

        public void buy(String username, String bookname, double price) {

            System.out.println("用户名:"+username);

            System.out.println("书名:"+bookname);

            System.out.println("价格"+price);
             }

        public void pinlun(String username, String pinlunleirong) {

            System.out.println("评论人:"+username);

            System.out.println("评论类容:"+pinlunleirong);

        }

    }

DaiLiLei1.java(使用xml配置的代理类):

    /*
     * 时间:2016年9月28日20:42:12
     * 程序功能:代理类
     * */
    package com.sc.daililei;
    import java.util.Arrays;
    import java.util.Date;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    public class DaiLiLei1 {

        // 后置通知,jp.getSignature().getName()可以获取当前执行的方法名

        // Arrays.toString(jp.getArgs())获取属性名

        public void logBefore(JoinPoint jp) {

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 开始执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

        }

        public void logAfter(JoinPoint jp) {

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 结束执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

        }

        public void logAround(ProceedingJoinPoint jp) throws Throwable {

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 结束执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

            Object obj = jp.proceed();

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 结束执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

        }

    }
DaiLiLei.java(使用注解配置的代理类):

    /*
     * 时间:2016年9月28日20:42:12
     * 程序功能:代理类,使用注解方配置
     * */

    package com.sc.daililei;
    import java.util.Arrays;
    import java.util.Date;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    @Aspect
    public class DaiLiLei {

        // 该方法相当于在这个位置定义一个切点,以下方法都使用这个切点

        @Pointcut("execution(* com.sc.biz.BookBizImpl .*(..))")

        public void heHe() {

        }

        // 后置通知,jp.getSignature().getName()可以获取当前执行的方法名

        // Arrays.toString(jp.getArgs())获取属性名

        @Before("heHe()")

        public void logBefore(JoinPoint jp) {

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 开始执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

        }

        @After("heHe()")

        public void logAfter(JoinPoint jp) {

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 结束执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

        }

        @Around("heHe()")

        public void logAround(ProceedingJoinPoint jp) throws Throwable {

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 结束执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

            Object obj = jp.proceed();   //此处为前置通知和后置通知的分界点

            System.out.println("[系统日志][" + new Date().toLocaleString() + "] 结束执行:"

            + jp.getSignature().getName() + "参数是:"

            + Arrays.toString(jp.getArgs()));

        }

    }

applicationContext.xml(Spring配置文件):

<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans ;
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop ;
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

        
    <!-- 使用xml配置 -->
    <!-- <bean id="bookBizImpl" class="com.sc.biz.BookBizImpl"></bean>
    <bean id="daiLiLei" class="com.sc.daililei.DaiLiLei1"></bean>
    <aop:config>
       <aop:aspect id="dai" ref="daiLiLei">
         <aop:pointcut expression="execution(* com.sc.biz.BookBizImpl .*(..))" id="p"/>
         <aop:before method="logBefore" pointcut-ref="p"/>
         <aop:after method="logAfter" pointcut-ref="p"/>
         <aop:around method="logAround" pointcut-ref="p"/>
       </aop:aspect>
    </aop:config> -->
    
    <!-- 使用注解配置 -->
    <bean id="bookBizImpl" class="com.sc.biz.BookBizImpl"></bean>
    <bean id="daiLiLei" class="com.sc.daililei.DaiLiLei"></bean>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

切面其实是一个普通的类,然后在配置文件中将它声明称切面

关于在配置文件中声明切面:
<aop:pointcut expression="execution(* com.sc.biz.BookBizImpl .*(..))" id="p"/>  
  expression里面的值设置方法:
1、任意公共方法的执行:
       expression(public * *(..))
 2、任意一个以set开始的方法的执行:
      
expression(* set* (..))
 
3、AccountService接口定义的任何方法的执行:
      
expression(* com.sc.service. AccountService.*(..) )       
 4、在service包中定义的任何方法的执行:
       
expression(* com.sc.service.*.*(..))

 5、在service包或其子包中定义的任一方法的执行:
        expression(* com.sc.service..*.*(..))  

在配置文件中使用切面:
例如:<aop:before method="logBefore" pointcut-ref="p"/>
声明通知:
常用: <aop:before/>
          <aop:after/>
          <aop:around/>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值