Spring AOP 三种实现方式

Spring AOP 三种实现方式

1.动态代理实现AOP基于XML的配置方式

业务逻辑接口

package com.chen.service;
public interface IOrderService {
    String creatNewOrder(int orderMoney);
    void payForOrder();
}

业务逻辑实现类

@Service("orderServiceBean")
public class OrderServiceImpl implements IOrderService {
    @Override
    public String creatNewOrder(int orderMoney) {
        System.out.println("【业务层】创建新订单,订单金额为:"+orderMoney);
       // Integer.parseInt("soso");
        return UUID.randomUUID().toString();
    }
    @Override
    public void payForOrder() {
        System.out.println("【业务层】支付订单");
    }
}

通知类


/**
 * 日志通知
 */
public class LogAdvice implements MethodBeforeAdvice ,AfterReturningAdvice{
    /**
     * 前置通知(将会在目标对象的目标方法执行前调用)
     * @param method 目标方法
     * @param objects 参数列表
     * @param target 目标对象
     * @throws Throwable
     */
    @Override
    public void before(Method method, Object[] objects, Object target) throws Throwable {
        System.out.println("目标对象:"+target);
        System.out.println("目标方法:"+method.getName());
        System.out.println("传入参数:"+ Arrays.toString(objects));
        System.out.println("【日志】"+target+"的"+method.getName()+"方法于"+new Date()+"被执行");
    }

    /**
     * 后置通知
     * @param result
     * @param method
     * @param objects
     * @param target
     * @throws Throwable
     */
    @Override
    public void afterReturning(Object result, Method method, Object[] objects, Object target) throws Throwable {
        System.out.println("返回值"+result);
        System.out.println("目标对象:"+target);
        System.out.println("目标方法:"+method.getName());
        System.out.println("传入参数:"+ Arrays.toString(objects));
        System.out.println("【日志】"+target+"的"+method.getName()+"方法于"+new Date()+"执行结束");
    }
}

XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--被代理对象    -->
    <bean id="orderServiceBean" class="com.chen.service.impl.OrderServiceImpl"/
    <!--通知    -->
    <bean id="logAdviceBean" class="com.chen.advice.LogAdvice"/>
    <bean id="performanceAdviceBean" class="com.chen.advice.PerformanceAdvice"/>

    <!--切入点:通过正则表达式描述指定切入点-->
    <bean id="methodPointcutBean" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <!--注入正则表达式:描述哪些方法为切入点-->
        <property name="pattern" value=".*creat.*"/><!--以creat开头的方法-->
    </bean>

    <!--高级通知(Advisor) =通知(Advice)+切入点(Pointcut)-->
    <bean id="performanceAdvisorBean" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<!--        注入切入点-->
        <property name="pointcut" ref="methodPointcutBean"/>
<!--        注入通知-->
        <property name="advice" ref="performanceAdviceBean"/>
    </bean>


    <!-- 自动代理创建   -->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <!--Bean名称规则(数组)指定哪些bean创建代理      -->
        <property name="beanNames">
            <list>
                <value>*ServiceBean</value>
            </list>
        </property>
        <!--通知列表:需要执行哪些通知     -->
        <property name="interceptorNames">
            <list>
                <value>logAdviceBean</value>
                <value>performanceAdvisorBean</value>
            </list>
        </property>
    </bean>
</beans>
2.使用Aspect实现切面,使用Spring AOP 进行配置

切面类

/**
 * 使用AspectJ实现切面(普通POJO的实现方式)
 */
public class LogAspect {
    /**
     * 前置通知
     * @param joinPoint
     */
    public void beforeAdvice(JoinPoint joinPoint){
        System.out.println("========【使用AspectJ实现前置通知】=========");
        System.out.println("目标对象:"+joinPoint.getTarget());
        System.out.println("目标方法:"+joinPoint.getSignature().getName());
        System.out.println("参数列表:"+ Arrays.toString(joinPoint.getArgs()));
        System.out.println("============================================");
    }
    /**
     * 后置通知:方法正常执行后,有返回值,执行该后置通知;如果该方法执行出现异常,则不执行该后置通知
     */
    public void afterReturningAdvice(JoinPoint joinpoint,Object returnVal){
        System.out.println("==========【使用AspectJ实现后置通知】开始==================");
        System.out.println("目标对象:" + joinpoint.getTarget());
        System.out.println("目标方法:" + joinpoint.getSignature().getName());
        System.out.println("参数列表:" + joinpoint.getArgs());
        System.out.println("返回值:" + returnVal);
        System.out.println("==========【使用AspectJ实现后置通知】结束==================");
    }
    /**
     * 后置通知
     */
    public void afterAdvice(JoinPoint joinpoint){
        System.out.println("==========【使用AspectJ实现后置通知】开始==================");
        System.out.println("目标对象:" + joinpoint.getTarget());
        System.out.println("目标方法:" + joinpoint.getSignature().getName());
        System.out.println("参数列表:" + joinpoint.getArgs());
        System.out.println("==========【使用AspectJ实现后置通知】结束==================");
    }
    /**
     * 异常通知:方法出现异常时,执行该通知
     * @param joinpoint
     * @param ex
     */
    public void throwingAdvice(JoinPoint joinpoint,Exception ex){
        System.out.println("==========【使用AspectJ实现异常通知】开始==================");
        System.out.println("目标对象:" + joinpoint.getTarget());
        System.out.println("目标方法:" + joinpoint.getSignature().getName());
        System.out.println("出现异常:" + ex.getMessage());
        System.out.println("==========【使用AspectJ实现异常通知】结束==================");
    }

    /**
     * 环绕通知
     */
    public Object aroundAdvice(ProceedingJoinPoint joinpoint) throws Throwable {

        System.out.println("#########$环绕通知的前置部分$###############");
        Object returnVal = joinpoint.proceed();
        System.out.println("#########$环绕通知的后置部分$###############");

        return returnVal;
    }

}

XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--业务组件-->
    <bean id="orderServiceBean" class="com.chen.service.impl.OrderServiceImpl"/>
    <!-- 日志AspectJ切面-->
    <bean  id="logAspectBean" class="com.chen.advice.LogAspect"/>


    <!--使用Aspect实现切面,使用Spring AOP 进行配置-->
        <aop:config>
        <!-- 配置切面-->
        <!-- 注入切面bean-->
            <aop:aspect ref="logAspectBean">
                <!--定义Pointcut:通过expression表达式,来查找特定的方法(pointcut)-->
                <aop:pointcut id="serviceMethodPointcut" expression="execution(* com.chen.service.impl.*.creat*(..))"/>
                <!--配置前置通知 -->
                <!--在pointcut切入点(serviceMethodPointcut)查找到的方法执行前,执行当前logAspectBean的beforeAdvice-->
                <aop:before method="beforeAdvice" pointcut-ref="serviceMethodPointcut"/>

                <!--配置后置通知-->
                <!--returning属性:配置当前方法中用来接收返回值的参数名-->
                <aop:after-returning returning="returnVal" method="afterReturningAdvice" pointcut-ref="serviceMethodPointcut"/>
                <aop:after method="afterAdvice" pointcut-ref="serviceMethodPointcut"/>

                <!--配置异常通知-->
                <!--throwing属性:配置当前方法中用来接收当前异常的参数名-->
                <aop:after-throwing throwing="ex" method="throwingAdvice" pointcut-ref="serviceMethodPointcut"/>

                <!--配置环绕通知-->
                <aop:around method="aroundAdvice" pointcut-ref="serviceMethodPointcut"/>

            </aop:aspect>
        </aop:config>

    </beans>
3.使用AspectJ实现切面(注解的实现方式)

​ 切面类


/**
 * 使用AspectJ实现切面(注解的实现方式)
 */

//声明当前类为Aspect切面,并交给Spring容器管理
@Aspect
@Component
public class LogAnotationAspect {
    private static final String POINTCUT_EXPRESSION = "execution(* com.chen.service.impl.*.creat*(..) )";

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before(POINTCUT_EXPRESSION)
    public void beforeAdvice(JoinPoint joinPoint){
        System.out.println("========【使用AspectJ实现前置通知】=========");
        System.out.println("目标对象:"+joinPoint.getTarget());
        System.out.println("目标方法:"+joinPoint.getSignature().getName());
        System.out.println("参数列表:"+ Arrays.toString(joinPoint.getArgs()));
        System.out.println("============================================");
    }
    /**
     * 后置通知:方法正常执行后,有返回值,执行该后置通知;如果该方法执行出现异常,则不执行该后置通知
     */
    @AfterReturning(value=POINTCUT_EXPRESSION,returning = "returnVal")
    public void afterReturningAdvice(JoinPoint joinpoint,Object returnVal){
        System.out.println("==========【使用AspectJ实现后置通知】开始==================");
        System.out.println("目标对象:" + joinpoint.getTarget());
        System.out.println("目标方法:" + joinpoint.getSignature().getName());
        System.out.println("参数列表:" + joinpoint.getArgs());
        System.out.println("返回值:" + returnVal);
        System.out.println("==========【使用AspectJ实现后置通知】结束==================");
    }
    /**
     * 后置通知
     */
    @After(POINTCUT_EXPRESSION)
    public void afterAdvice(JoinPoint joinpoint){
        System.out.println("==========【使用AspectJ实现后置通知】开始==================");
        System.out.println("目标对象:" + joinpoint.getTarget());
        System.out.println("目标方法:" + joinpoint.getSignature().getName());
        System.out.println("参数列表:" + joinpoint.getArgs());
        System.out.println("==========【使用AspectJ实现后置通知】结束==================");
    }
    /**
     * 异常通知:方法出现异常时,执行该通知
     * @param joinpoint
     * @param ex
     */
    @AfterThrowing(value = POINTCUT_EXPRESSION,throwing = "ex")
    public void throwingAdvice(JoinPoint joinpoint,Exception ex){
        System.out.println("==========【使用AspectJ实现异常通知】开始==================");
        System.out.println("目标对象:" + joinpoint.getTarget());
        System.out.println("目标方法:" + joinpoint.getSignature().getName());
        System.out.println("出现异常:" + ex.getMessage());
        System.out.println("==========【使用AspectJ实现异常通知】结束==================");
    }

    /**
     * 环绕通知
     */
    @Around(POINTCUT_EXPRESSION)
    public Object aroundAdvice(ProceedingJoinPoint joinpoint) throws Throwable {

        System.out.println("#########$环绕通知的前置部分$###############");
        Object returnVal = joinpoint.proceed();
        System.out.println("#########$环绕通知的后置部分$###############");

        return returnVal;
    }
}

​ XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

        <!--自动扫描器-->
        <context:component-scan base-package="com.chen"/>
        <!--配置AspectJ的自动代理-->
        <aop:aspectj-autoproxy/>

</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值