代码改变世界

spring aop中aspect和advisor的区别

2020-06-02 11:41  Tony、  阅读(786)  评论(0编辑  收藏  举报

在使用xml配置spring aop的时候一般有两种方式

 1  <aop:advisor>  :基本上用于事务管理

 2  <aop:aspect>  :日志 缓存 增强等功能

实现方式

  <aop:advisor> 需要实现接口

    1 环绕切: 实现 MethodInterceptor 接口

    2 前切:实现 MethodBeforeAdvice 接口

    3 后切:实现 MethodAfterAdvice 接口

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class MyBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("执行前置通知");
    }
}
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAround implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("环绕-前置");
        Object proceed = methodInvocation.proceed();
        System.out.println("环绕-后置");
        return proceed;


    }
}
import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class MyAfterAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行后置通知");
    }
}
public interface BaseServlet {
    void run();
}
public class MyServlet  implements  BaseServlet {

    @Override
    public void run() {
        System.out.println("MyServlet run");
    }
}
import com.my.servlet.BaseServlet;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AopAdvisorApp {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("adviceApplicationContext.xml");
        BaseServlet myServlet = ac.getBean("myServlet", BaseServlet.class);
        myServlet.run();
    }
}
<?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:aop="http://www.springframework.org/schema/aop"
       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="myServlet" class="com.my.servlet.MyServlet"/>

    <bean id="myBeforeAdvice" class="com.my.aop.advisor.MyBeforeAdvice"/>
    <bean id="myAfterAdvice" class="com.my.aop.advisor.MyAfterAdvice"/>
    <bean id="myAround" class="com.my.aop.advisor.MyAround"/>
    <!-- Aop配置 -->
    <aop:config>
        <aop:pointcut id="mypoint" expression="execution(* com.my.servlet.*.*(..))"/>
        <aop:advisor advice-ref="myBeforeAdvice" pointcut-ref="mypoint"/>
        <aop:advisor advice-ref="myAfterAdvice" pointcut-ref="mypoint"/>
        <aop:advisor advice-ref="myAround" pointcut-ref="mypoint"/>
    </aop:config>

</beans>

执行结果:


六月 02, 2020 3:07:02 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17f052a3: startup date [Tue Jun 02 15:07:02 CST 2020]; root of context hierarchy
六月 02, 2020 3:07:02 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [advisorApplicationContext.xml]
执行前置通知
环绕-前置
MyServlet run
环绕-后置
执行后置通知

 

<aop:aspect> 不需要实现接口

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
    public void before() {
        System.out.println("执行前置通知 before");
    }
    public void after() {
        System.out.println("执行后置通知 before");
    }

    public  Object arround(ProceedingJoinPoint p) throws Throwable {
        System.out.println("环绕前置");
        Object proceed = p.proceed();
        System.out.println("环绕后置");
        return proceed;
    }

}
public class AopAspectApp {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("aspectApplicationContext.xml");
        BaseServlet myServlet = ac.getBean("myServlet", BaseServlet.class);
        myServlet.run();
    }
}
<?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:aop="http://www.springframework.org/schema/aop"
       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="myServlet" class="com.my.servlet.MyServlet"/>

    <bean id="myAdvice" class="com.my.aop.aspect.MyAdvice"/>

    <!-- Aop配置 -->
    <aop:config>
        <aop:aspect ref="myAdvice">
            <aop:pointcut id="mypoint" expression="execution(* com.my.servlet.*.*(..))"/>
            <aop:before method="before" pointcut-ref="mypoint"></aop:before>
            <aop:after method="after" pointcut-ref="mypoint"></aop:after>
            <aop:around method="arround" pointcut-ref="mypoint"></aop:around>

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

</beans>

执行结果:

六月 02, 2020 3:06:24 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17f052a3: startup date [Tue Jun 02 15:06:24 CST 2020]; root of context hierarchy
六月 02, 2020 3:06:24 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [aspectApplicationContext.xml]
执行前置通知 before
环绕前置
MyServlet run
环绕后置
执行后置通知 before