spring AOP切面实现

1.注解实现

第一步:先准备几个javaBean对象

@Controller
public class UserController {
    public void test(){
        System.out.println("UserController.test");
    }
}

@Repository
public class UserDao {
    public void test(){
        System.out.println("UserDao.test");
    }
}

@Service
public class UserService {
    public void test(){
        System.out.println("UserService.test");
    }
}

第二步:定义切面

/**
 * Aspect是定义这个类为一个切面
 * 切面由:切入点和通知组成
 * 切入点:要拦截哪些类的哪些方法
 * 通知:定义拦截方法后做什么
 */
@Component
@Aspect
public class LogCut {

    /**
     * 切入点就用Pointcut("匹配规则")这个注解表示要拦截哪些方法
     *常见切入点表达式
     * 表达式中的第一个*表示的是方法修饰的范围(public private protected)如果取值是*号,则表示所有范围
     * 1.执行所有公共的方法  @Pointcut("execution(public *(..))")
     * 2.执行任意的set方法   @Pointcut("execution(* set*(..))")
     * 3.设置指定包(com.zks.service)下的任意类的任意方法@Pointcut("execution(* com.zks.service.*.*(..))")
     * 4.设置指定包及子包(com.zks.service)下的任意类的任意方法@Pointcut("execution(* com.zks.service..*.*(..))")
     *
     */
    @Pointcut("execution(* com.zks.service.*.*(..))")
    public void cut(){

    }

    /**
     * 声明前置通知,并将通知应用到指定的切入点上
     *    目标类方法执行前,执行该通知
     */
    @Before(value = "cut()")//通知指向前面的切入点
    public void before(){
        System.out.println("前置通知");
    }

    /**
     * 声明返回通知,并将通知应用到指定的切入点上
     *   目标类执行完后并且没有异常,执行该通知
     */
    @AfterReturning(value = "cut()")
    public void afterReturn(){
        System.out.println("返回通知");
    }

    /**
     *  声明最终通知,并将通知应用到指定的切入点上
     *    目标类的方法执行后,执行该通知(有异常和无异常都行)
     *
     */
    @After(value = "cut()")
    public void after(){
        System.out.println("最终通知");
    }

    /**
     * 声明异常通知,并将通知应用到指定的切入点上
     *    目标类的方法在执行异常时,执行该通知
     */
    @AfterThrowing(value = "cut()",throwing = "e")
    public void afterThrow( Exception e ){
        System.out.println("异常通知。。。异常原因:"+e.getMessage());
    }

    /**
     * 声明环绕通知,并将通知应用到指定的切入点上
     *   目标类的方法执行前后都可以通过环绕通知定义响应的处理
     *   需要通过显示调用的方法,否则无法访问指定的方法 pjp.proceed()
     * @param pjp
     * @return
     */
    @Around(value = "cut()")
    public Object around(ProceedingJoinPoint pjp){
        System.out.println("环绕通知-前置通知");
        Object object=null;
        try{
             object=pjp.proceed();//要有环绕通知,就必须要执行proceed()这个方法
//            System.out.println(pjp.getTarget());
            System.out.println("环绕通知-返回通知");
        }catch (Throwable throwable){
            throwable.printStackTrace();
            System.out.println("环绕通知-异常通知");
        }
        System.out.println("环绕通知-最终通知");
        return object;
    }


}

第三步:测试

public class aoptest {
    public static void main(String[] args) {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
        UserService userService= (UserService) applicationContext.getBean("userService");
        userService.test();
    }
}

通过xml实现切面

需要自己写配置文件了

<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
         https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--    上面的命名空间xmlns和网址xsi是要按顺序一一对应的-->
    <!--    这是开启自动化扫描-->
    <context:component-scan base-package="com.zks"/>
<!--    &lt;!&ndash;    开启AOP代理&ndash;&gt;-->
<!--    <aop:aspectj-autoproxy/>-->
<!--    &lt;!&ndash;    <context:annotation-config></context:annotation-config>&ndash;&gt;-->
<!--    &lt;!&ndash;    &lt;!&ndash;    <bean id="roleService" class="com.zks.service.RoleService " init-method="init"/>&ndash;&gt;&ndash;&gt;-->

<!--    aop的相关配置-->
    <aop:config>
<!--        aop切面 ref是类名,代表切面-->
        <aop:aspect ref="logCut2">
<!--            aop切入点 id是方法名-->
            <aop:pointcut id="cut" expression="execution(* com.zks.service..*.*(..))"/>
<!--            配置前置通知,设置前置通知对应的方法名和切入点-->
            <aop:before method="before" pointcut-ref="cut"/>
<!--            返回通知-->
            <aop:after-returning method="afterReturn" pointcut-ref="cut"/>
<!--            异常通知-->
            <aop:after-throwing method="afterThrow" pointcut-ref="cut" throwing="e"/>
<!--            最终通知-->
            <aop:after method="after" pointcut-ref="cut"/>
<!--         环绕通知   -->
            <aop:around method="around" pointcut-ref="cut"/>
        </aop:aspect>

    </aop:config>
</beans>

定义的切面如下:没有注解了

@Component
public class LogCut2 {

    public void cut(){

    }

    /**
     * 声明前置通知,并将通知应用到指定的切入点上
     *    目标类方法执行前,执行该通知
     */

    public void before(){
        System.out.println("前置通知");
    }

    /**
     * 声明返回通知,并将通知应用到指定的切入点上
     *   目标类执行完后并且没有异常,执行该通知
     */

    public void afterReturn(){
        System.out.println("返回通知");
    }

    /**
     *  声明最终通知,并将通知应用到指定的切入点上
     *    目标类的方法执行后,执行该通知(有异常和无异常都行)
     *
     */

    public void after(){
        System.out.println("最终通知");
    }

    /**
     * 声明异常通知,并将通知应用到指定的切入点上
     *    目标类的方法在执行异常时,执行该通知
     */

    public void afterThrow( Exception e ){
        System.out.println("异常通知。。。异常原因:"+e.getMessage());
    }

    /**
     * 声明环绕通知,并将通知应用到指定的切入点上
     *   目标类的方法执行前后都可以通过环绕通知定义响应的处理
     *   需要通过显示调用的方法,否则无法访问指定的方法 pjp.proceed()
     * @param pjp
     * @return
     */

    public Object around(ProceedingJoinPoint pjp){
        System.out.println("环绕通知-前置通知");
        Object object=null;
        try{
            object=pjp.proceed();//要有环绕通知,就必须要执行proceed()这个方法
//            System.out.println(pjp.getTarget());
            System.out.println("环绕通知-返回通知");
        }catch (Throwable throwable){
            throwable.printStackTrace();
            System.out.println("环绕通知-异常通知");
        }
        System.out.println("环绕通知-最终通知");
        return object;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值