Spring AOP几种方式的使用

来源:互联网 发布:熊猫杀姐姐知乎 编辑:程序博客网 时间:2024/06/06 12:48

引入依赖

<spring-version>4.2.3.RELEASE</spring-version><dependency>    <groupId>junit</groupId>    <artifactId>junit</artifactId>    <version>4.11</version>    <scope>test</scope></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-core</artifactId>    <version>${spring-version}</version><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-beans</artifactId>    <version>${spring-version}</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-context</artifactId>    <version>${spring-version}</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-test</artifactId>    <version>${spring-version}</version></dependency><dependency>    <groupId>org.aspectj</groupId>    <artifactId>aspectjrt</artifactId>    <version>1.8.8</version></dependency><dependency>    <groupId>org.aspectj</groupId>    <artifactId>aspectjweaver</artifactId>    <version>1.8.8</version></dependency>

Service

HelloService.class

public interface HelloService {    /**     *  hello method     */    void hello(String words);}

HelloServiceImpl .class

@Service("helloServiceImpl")public class HelloServiceImpl implements HelloService {    @Override    public void hello(String words) {        System.out.println(words);        int i = 1 / 0;    }}

方式一:使用MethodInterceptor

切面类 LogInterceptor.class

import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;/** * @author yuyufeng * @date 2017/11/14 */public class LogInterceptor implements MethodInterceptor {    @Override    public Object invoke(MethodInvocation invocation) throws Throwable {        System.out.println("#before");        Object ret = invocation.proceed();        System.out.println("#after");        return ret;    }}

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"       xmlns:context="http://www.springframework.org/schema/context"       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-4.0.xsd">    <context:component-scan base-package="learn.service.impl"/>    <bean id="logInterceptor" class="learn.interceptor.LogInterceptor"></bean>    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">        <property name="beanNames">            <value>*ServiceImpl</value>        </property>        <!--强制代理目标类(cglib)-->        <property name="proxyTargetClass" value="true"/>        <property name="interceptorNames">            <list>                <value>logInterceptor</value>            </list>        </property>    </bean></beans>

测试

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath:spring/spring-service.xml"})public class Demo1 {    @Autowired    private HelloService helloService;    @Test    public void test() {        System.out.println("Demo1.test");    }    @Test    public void testHelloService() {        try{            helloService.hello("hello 你好~");        }catch (Exception e){            System.out.println("出现异常");        }    }}

执行结果

#beforehello 你好~出现异常

方式二:使用@Aspect方式

配置Aspect类

import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;import java.lang.reflect.Method;/** * @author yuyufeng * @date 2017/11/14 */@Aspectpublic class LogAspect {    /**     * 方法前执行     * @param point     */    @Before("execution(* learn.service.impl.*.*(..))")    public void methodBefore(JoinPoint point) {        handleMethod(point);        System.out.println("LogAspect.methodBefore");    }    /**     * 无论方法以何种方式结束,都会执行(类似于finally)     * @param point     */    @After("execution(* learn.service.impl.*.*(..))")    public void methodAfter(JoinPoint point) {        System.out.println("LogAspect.methodAfter");    }    /**     * 环绕执行     * @param proceedingJoinPoint     * @return     * @throws Throwable     */    @Around(value = "execution(* learn.service.impl.*.*(..))")    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {        handleMethod(proceedingJoinPoint);        //调用核心逻辑        System.out.println("-----Start of aroundAdvice()-----");        Object retVal = proceedingJoinPoint.proceed();        System.out.println("-----End of aroundAdvice()------");        return retVal;    }    /**     * Throw后执行     * @param point     * @param ex     */    @AfterThrowing(pointcut = "execution(* learn.service.impl.*.*(..))", throwing = "ex")    public void doAfterThrowingTask(JoinPoint point,Exception ex) {        System.out.println(ex.toString());    }    /**     * 运行方法后执行     * @param joinPoint     * @param retVal     */    @AfterReturning(value = "execution(* learn.service.impl.*.*(..))",returning="retVal")    public void doAfterReturning(JoinPoint joinPoint,Object retVal){        System.out.println("LogAspect.doAfterReturning:"+retVal);    }    /**     * 获取方法名称     *     * @param joinPoint     * @return     * @throws Exception     */    public static String handleMethod(JoinPoint joinPoint){        Class<?> clazz = joinPoint.getTarget().getClass();        String name = joinPoint.getSignature().getName();        Object[] parameterTypes = joinPoint.getArgs();        System.out.println(name);        for (Object parameterType : parameterTypes) {            System.out.println("# "+parameterType);        }        for (Method method : clazz.getDeclaredMethods()) {            System.out.println("* "+method.getName());        }        return "";    }}

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"       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.0.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-4.0.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">    <context:component-scan base-package="learn.service.impl"/>      <!--强制代理目标类(cglib) proxy-target-class="true"-->        <aop:aspectj-autoproxy />        <bean id="logAspect" class="learn.aspect.LogAspect"></bean></beans>

运行测试执行类Demo1.class,得到结果

hello# hello 你好~* hello-----Start of aroundAdvice()-----hello# hello 你好~* helloLogAspect.methodBeforehello 你好~LogAspect.methodAfterjava.lang.ArithmeticException: / by zero出现异常

备注

切入点表达式 execution (* com.sample.service.impl...(..))
整个表达式可以分为五个部分:
1、execution(): 表达式主体。
2、第一个号:表示返回类型,号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
4、第二个号:表示类名,号表示所有的类。
5、(..):最后这个星号表示方法名,号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

原创粉丝点击