加载中...
加载中...
aspectJ开发aop


aspectJ开发aop

选择spring的AOP还是AspectJ?

spring有自己的AOP。功能已经基本够用了,除非你的要在接口上动态代理或者方法拦截精确到getter和setter。


在使用AOP的时候,用xml还是注解的方式(@Aspect)?
1)如果使用xml方式,不需要任何额外的jar包。

2)如果使用@Aspect方式,你就可以在类上直接一个@Aspect就搞定,不用在xml里配了。但是这需要额外的jar包( aspectjweaver.jar)。因为spring直接使用AspectJ的注解功能,并不是核心功能 !!!

注意:无论是使用spring aop还是 aspectj都需要aspectjweaver.jar spring-aop.jar这两个jar包。

aspectJ是基于java开发的aop框架,自spring2.0以后,springaop引入对他支持。

使用aspectJ实现aop由两种方式:基于xml和基于注解

相对来说注解方式更加简单,开发中常用注解方式。

基于xml声明式aspectJ

package com.lx.aspectj.xml;

 

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

 

/**

 * 切面类֪

 * @author Administrator

 *

 */

public class MyAspect {

//前置通知֪

    public void myBefore(JoinPoint joinPoint) {

       System.out.print("前置通知:模拟执行权限检查...,");

       System.out.print("目标类是:"+joinPoint.getTarget());

       System.out.println(",被植入增强目标为:"+joinPoint.getSignature());

    }

    //后置通知֪

    public void myAfterReturning(JoinPoint joinPoint) {

       System.out.println("后置通知:模拟记录日志...,");

       System.out.println(",被植入增强目标为:"+joinPoint.getSignature().getName());

    }

    /**

     * 环绕通知֪

     * @param proceedingJoinPoint JoinPoint的子接口,表示可以执行目标方法

     * @return Object

     * 必须接收一个参数,类型为ProceedingJoinPoint

     * @必须 throws Throwable

     */

    public Object myAround(ProceedingJoinPoint proceedingJoinPoint)

           throws Throwable{

       //开始

       System.out.println("环绕开始:开启之前,模拟开启事务...");

       //执行当前目标方法

       Object obj=proceedingJoinPoint.proceed();

       //结束

       System.out.println("环绕结束:模拟关闭事务...");

       return obj;

    }

    //异常通知֪

    public void myAfterThrowing(JoinPoint joinPoint,Throwable e) {

       System.out.println("异常通知:出错了"+e.getMessage());

    }

    //最终通知֪

    public void myAfter() {

       System.out.println("最终通知:模拟方法结束后的释放资源...");

    }

   

   

}

 

<?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:aop="http://www.springframework.org/schema/aop"

    xsi:schemaLocation="

        http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context-4.3.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <!-- 1 目标类  -->

    <bean id="userDao" class="com.lx.jdk.UserDaoImpl"></bean>

    <!-- 2切面 -->

    <bean id="myAspect" class="com.lx.aspectj.xml.MyAspect"></bean>

    <!-- 3aop编程 -->

    <aop:config>

       <!-- 配置切面 -->

       <aop:aspect ref="myAspect">

           <!-- 3.1配置切入点,通知最后增强哪些方法 -->

           <aop:pointcut expression="execution(* com.lx.jdk.*.*(..))"

           id="myPointCut"></aop:pointcut>

           <!-- 3.2关联通知Advice和切入点pointCut -->

           <!-- 3.2.1前置通知 -->

           <aop:before method="myBefore" pointcut-ref="myPointCut"></aop:before>

           <!-- 3.2.2后置通知,在方法返回之后执行,就可获得返回值

           returing属性:用于设置后置通知的第二个参数的名称,类型Object-->

           <aop:after-returning method="myAfterReturning"

           pointcut-ref="myPointCut" returning="returnVal"></aop:after-returning>

           <!-- 3.2.3环绕通知 -->

           <aop:around method="myAround" pointcut-ref="myPointCut"></aop:around>

           <!-- 3.2.4抛出异常 通知,如果程序无异常将不会执行增强,

           throwing属性:设置通知第二个参数的名称,类型Throwable-->

           <aop:after-throwing method="myAfterThrowing"

           pointcut-ref="myPointCut" throwing="e"></aop:after-throwing>

           <!-- 3.2.5最终通知:无论程序发生任何情况,都执行 -->

           <aop:after method="myAfter" pointcut-ref="myPointCut"></aop:after>

      

       </aop:aspect>

    </aop:config>

   

   

</beans>

package com.lx.aspectj.xml;

 

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import com.lx.jdk.UserDao;

 

public class TestXmlAspect {

 

    public static void main(String[] args) {

       // TODO Auto-generated method stub

       String xmlpath="com/lx/aspectj/xml/applicationContext.xml";

       ApplicationContext   applicationContext=new

              ClassPathXmlApplicationContext(xmlpath);

       UserDao userDao=(UserDao)applicationContext.getBean("userDao");

       userDao.addUser();

    }

 

}

 


基于注解的声明式aspectJ

注解名称

描述

@Aspect

定义一个切面

@Pointcut

定义切面表达式

@Before

定义前置通知,相当于BeforeAdvice

@AfterReturning

定义后置通知,相当于AfterReturningAdvice

@Around

定义环绕通知,相当于MethodIntercetor

@AfterThrowing

定义异常通知来处理程序中未处理的异常,相当于ThrowAdvice

@After

定义最终final通知

根据需要在切入点不同位置的切入内容

使用@Before在切入点开始处切入内容

使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)

使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容

使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑

使用@After在切入点结尾处切入内容  


package com.lx.aspectj.annotation;

 

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;

 

/**

 * 切面类֪

 * @author Administrator

 *

 */

@Aspect

@Component

public class MyAspect {

    //定义切点表达式

    @Pointcut("execution(* com.lx.jdk.*.*(..))")

    //使用一个返回值为void,方法体为空的方法来命名切入点

    public void myPointCut(){};

   

    //前置通知

    @Before("myPointCut()")

    public void myBefore(JoinPoint joinPoint) {

       System.out.print("前置通知:模拟执行权限检查...,");

       System.out.print("目标类是:"+joinPoint.getTarget());

       System.out.println(",被植入增强目标为:"+joinPoint.getSignature());

    }

    //后置通知

    @AfterReturning("myPointCut()")

    public void myAfterReturning(JoinPoint joinPoint) {

       System.out.println("后置通知:模拟记录日志...,");

       System.out.println(",被植入增强目标为:"+joinPoint.getSignature().getName());

    }

    /**

     * 环绕通知

     * @param proceedingJoinPoint JoinPoint的子接口,表示可以执行目标方法

     * @return Object

     * 必须接收一个参数,类型为ProceedingJoinPoint

     * @必须 throws Throwable

     */

    @Around("myPointCut()")

    public Object myAround(ProceedingJoinPoint proceedingJoinPoint)

           throws Throwable{

       //开始

       System.out.println("环绕开始:开启之前,模拟开启事务...");

       //执行当前目标方法

       Object obj=proceedingJoinPoint.proceed();

       //结束

       System.out.println("环绕结束:模拟关闭事务...");

       return obj;

    }

    //异常通知

    @AfterThrowing(value="myPointCut()", throwing="e")

    public void myAfterThrowing(JoinPoint joinPoint,Throwable e) {

       System.out.println("异常通知:出错了"+e.getMessage());

    }

    //最终通知

    @After("myPointCut()")

    public void myAfter() {

       System.out.println("最终通知:模拟方法结束后的释放资源...");

    }

   

   

}

 

 

package com.example.springBootdemo.aop;

 

import java.util.Objects;

 

import javax.servlet.http.HttpServletRequest;

 

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.core.annotation.Order;

import org.springframework.stereotype.Component;

import org.springframework.web.context.request.RequestContextHolder;

import org.springframework.web.context.request.ServletRequestAttributes;

/**

 * 切面类,日志

 * @author luolei

 * @date 2019211

 */

@Aspect //声明为切面类

@Component

@Order(1) //标记切点的优先级,i越小,优先级越高

public class MyAspectLog {

   

    //定义切点表达式:*,第一个返回值,第二个类名,第三个方法名

     @Pointcut("execution(public * com.example.springBootdemo.service.*.*(..))")

    //使用一个返回值为void,方法体为空的方法来命名切入点

    public void myPointCut(){};

   

    private final Logger logger = LoggerFactory.getLogger(getClass());

   

    //前置通知

    @Before("myPointCut()")

    public void myBefore(JoinPoint joinPoint) {

       logger.info("-----------@Before 前置通知-----------");

       logger.info("前置通知:模拟执行权限检查...");

       logger.info("目标类是={}", joinPoint.getTarget());

       logger.info("被植入增强目标为={}", joinPoint.getSignature());

      

       ServletRequestAttributes attributes= (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();

        HttpServletRequest request =attributes.getRequest();

       //url

        logger.info("请求路径URL={}",request.getRequestURL());

        //method

        logger.info("请求方式Method={}",request.getMethod());

        //ip

        logger.info("请求IP={}",request.getRemoteAddr());

        //类方法

        logger.info("请求类方法ClassMethod={}",joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName());

        //参数

        logger.info("请求参数Args={}",joinPoint.getArgs());

    }

   

    //后置通知

/*  @AfterReturning("myPointCut()")

    public void myAfterReturning(JoinPoint joinPoint) {

       logger.info("-----------@AfterReturning 后置通知-----------");

       logger.info("后置通知:模拟记录日志...");

        logger.info("返回值 response={}", joinPoint.toString());

    }*/

   

    //后置通知

    @AfterReturning(returning = "objects", pointcut = "myPointCut()")

    public void myAfterReturning(Object objects) {

       logger.info("-----------@AfterReturning 后置通知-----------");

       logger.info("后置通知:模拟记录日志...");

        logger.info("返回值 response={}", objects);

    }

    /**

     * 环绕通知

     * @param proceedingJoinPoint JoinPoint的子接口,表示可以执行目标方法

     * @return Object

     * 必须接收一个参数,类型为ProceedingJoinPoint

     * @必须 throws Throwable

     */

    @Around("myPointCut()")

    public Object myAround(ProceedingJoinPoint proceedingJoinPoint)

           throws Throwable{

       //开始

       logger.info("-----------@Around 环绕通知start-----------");

       logger.info("环绕开始:开启之前,模拟开启事务...");

       long time = System.currentTimeMillis();

       //执行当前目标方法

       Object obj=proceedingJoinPoint.proceed();

       //结束

       logger.info("环绕结束:模拟关闭事务...");

       time = System.currentTimeMillis() - time;

        logger.info("方法用时Time={}", time +"(毫秒)");

        logger.info("-----------@Around 环绕通知end-----------");

       return obj;

    }

   

    //异常通知

    @AfterThrowing(value="myPointCut()", throwing="e")

    public void myAfterThrowing(JoinPoint joinPoint,Throwable e) {

       logger.info("-----------@AfterThrowing 异常通知-----------");

       logger.info("异常通知:出错了"+ e);

       logger.info("异常通知:出错了getStackTrace={}", e.getStackTrace());

       logger.info("异常通知:出错了Throwable...具体如下", e);

    }

   

    //最终通知

    @After("myPointCut()")

    public void myAfter() {

       logger.info("-----------@After 最终通知-----------");

       logger.info("最终通知:模拟方法结束后的释放资源...");

    }

   

   

}

 

<?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:aop="http://www.springframework.org/schema/aop"

    xsi:schemaLocation="

        http://www.springframework.org/schema/beans

        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd

        http://www.springframework.org/schema/context

        http://www.springframework.org/schema/context/spring-context-4.3.xsd

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

   

    <context:component-scan base-package="com.lx"/>

<!—启动基于注解的aspectJ --> 

<aop:aspactj-autoproxy/>

 

</beans>

package com.lx.aspectj.annotation;

 

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import com.lx.jdk.UserDao;

 

public class TestAnnotation {

 

    public static void main(String[] args) {

       // TODO Auto-generated method stub

       String xmlpath="com/lx/aspectj/annotaion/applicationContext.xml";

       ApplicationContext   applicationContext=new

              ClassPathXmlApplicationContext(xmlpath);

       UserDao userDao=(UserDao)applicationContext.getBean("userDao");

       userDao.addUser();

    }

 

}

 






没有更多推荐了 [去首页]
image
文章
357
原创
284
转载
73
翻译
0
访问量
199056
喜欢
47
粉丝
6
码龄
5年
资源
0

文章目录

加载中...
0
0