发表于: 2018-01-06 18:19:33

0 600


今天完成的事:

学习Aspectj实现AOP


遇到的困难:

1、利用注解向指定方法织入通知时,无参的方法可以成功,有参的方法没有成功,试了很久。

原因:切入点表达式写的不对,缺少方法中的 .. 

@Around("execution(* * ..ServiceImpl.*(..))")

对于无参的方法不写 .. 可以,但是有参的必须写,否则切入点表达式不完整。


2、【未解决】之前写好的项目,现在启动tomcat运行,出现

Error:Cannot build artifact 'task2springmvc:war exploded' because it is included into a circular dependency (artifact 'task2springmvc:war exploded', artifact 'task2-springmvc:war exploded')


我百度这个问题的解释是,循环依赖,即A依赖B,B依赖C,C依赖A,或者是A依赖于B,B依赖A

单元测试可以正常运行

pom文件中新加的两个jar包注释掉了,新加的类和之前的东西也没有关系,还是有这个问题


问题可能在,但是这里没办法删除啊






明天计划:


收获:

1、什么是Aspectj?

   AOP面向切面编程是一种思想,spring框架可以实现,Aspectj框架也可以实现,并且支持注解式开发,所有Spring框架引入了Aspectj框架。




一、注解式:


2、Aspectj的切入点表达式

@Around是环绕通知

@Around("execution(* * ..ServiceImpl.*(..))")

切入点表达式

execution()

返回值类型,方法名(参数名)是不可省略的

如上图,第一个 * 表示返回值类型是任意的,

第二个 * 表示包名,

第三个 .. 表示可以是多级包,

第四个ServiceImpl表示类名,

第五个 . * 表示指定类的所有方法

第六个 .. 表示方法的参数是任意的


举个例子:显示完整的方法名和切入点表达式

@Before("execution(* * ..ServiceImpl.*(..))")
public void after(JoinPoint jp){
System.out.println("前置通知切入点表达式:"+jp);
   System.out.println("前置通知方法签名:"+jp.getSignature());
   System.out.println("前置通知目标对象:"+jp.getTarget());
}

执行的结果:

前置通知切入点表达式:execution(int com.jnshu.IService.second(int))

前置通知方法签名:int com.jnshu.IService.second(int)

前置通知目标对象:com.jnshu.ServiceImpl@3bbc39f8


3、通知类型

所有通知类型都有JoinPoint参数

1)JoinPoint 

java.lang.Object[] getArgs():获取连接点方法运行时的入参列表; 
Signature getSignature() :获取连接点的方法签名对象; 
java.lang.Object getTarget() :获取连接点所在的目标对象; 

java.lang.Object getThis() :获取代理对象本身;  



@Before  前置通知

@AfterReturning  后置通知

    可以添加result参数,用于显示返回值

@Around  环绕通知

    环绕通知有方法的执行过程,所以必须有参数ProceedingJoinPoint,继承JoinPoint的子接口,环绕通知可以改变返回值结果,但是只有环绕通知的时候,虽然有 return result,但是不会将返回值result返回到控制台。

String name = pjp.getSignature().getName();
String name1 = pjp.getTarget().getClass().getName();
System.out.println("方法名;"+name+"    "+"类名"+name1);

@AfterThrowing 异常通知




4、定义的切面

@Aspect
//指定当前类为切面
public class MyAspectj {

//  环绕通知
   @Around("execution(* * ..ServiceImpl.*(..))")
public Object before(ProceedingJoinPoint pjp) throws Throwable {
long time1 = new Date().getTime();
       System.out.println("环绕通知,方法执行前");
       Object result = pjp.proceed();
       if(result != null){
int r1 = (Integer) result + 10;
       }

System.out.println("环绕通知,方法执行后");
       long time2 = new Date().getTime();
       System.out.println("执行方法用时:"+(time2-time1));
       return result;
   }

spring配置文件中内容

注册目标类,注册切面类,配置自动代理

<!--配置aspecctj的自动代理-->
<aop:aspectj-autoproxy/>
<!--注册目标类-->
   <bean id="service" class="com.jnshu.ServiceImpl"/>

<!--注册切面类-->
   <bean id="myAspectj" class="com.jnshu.MyAspectj"/>


二、xml式

spring配置文件中

<aop:before  />   表示前置方法

<!--xml式-->
   <!--注册目标类-->
   <bean id="service" class="com.jnshu.ServiceImpl"/>

   <!--注册切面类-->

   <bean id="aspectj2" class="com.jnshu.Aspectj2"/>

   <!--配置AOP-->

    <aop:config>
        <!--定义切入点,可以是好几个-->
        <aop:pointcut id="firstpoint1" expression="execution(* * ..ServiceImpl.first(..))"/>
        <!--定义切面-->
        <aop:aspect ref="aspectj2">
            <!--前置通知-->
            <aop:before method="before" pointcut-ref="firstpoint1"/>
        </aop:aspect>
    </aop:config>


两种方式都需要注册目标类和注册切面类



禅道 http://task.ptteng.com/zentao/my-task.html


返回列表 返回列表
评论

    分享到