网易Java Web微专业Spring-AOP容器作业

2016/10/9 posted in  Java  

完成一个基本的应用,提供若干个Service(>=2),每个Service提供基本的增删查改的接口(实现随意,比如输出一行信息),通过AOP保证所有所有的Service接口在正常调用返回后以及抛出异常时(Service接口模拟),打出如下信息:函数名称,函数参数,并说明发生的事件:正常返回或者抛出异常。

AOP模式示意图

作业描述

本次作业我设计了两个Service,分别是UserService和ProductService,每个Service分别提供增删改查操作(Print语句代替业务逻辑)。

  1. 配置Spring配置文件,加入AOP相关的xsd文件。并配置AOP。

    <?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:p="http://www.springframework.org/schema/p" 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/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    
        <!-- 引入AOP -->
        <aop:aspectj-autoproxy />
        <!-- 自动扫描annotation配置 -->
        <context:component-scan base-package="site.zhanjingbo" />
    
        <!-- 自定义的日志切面声明 -->
        <bean id="logAspect" class="site.zhanjingbo.aspect.LogAspect"></bean>
    </beans>
    
  2. 编写Service。以UserService为例。

    package site.zhanjingbo.service;
    import org.springframework.stereotype.Component;
    
    @Component
    public class UserService {
        public void add(String username) throws Exception {
            System.out.println("添加用户:" + username);
            throw new Exception("测试");
        }
        public void edit(String username) {
            System.out.println("添加用户:" + username);
        }
        public void del(String username) {
            System.out.println("删除用户:" + username);
        }
        public void find(String username) {
            System.out.println("查询用户:" + username);
        }
    }
    
  3. 编写Aspect,完成切面方法。

    package site.zhanjingbo.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    
    @Aspect
    public class LogAspect {
    
        /**
         * 正常返回时调用
         * @param jp调用点信息
         */
        @AfterReturning("execution(* site.zhanjingbo.service.*.*(..))")
        public void logAfterReturning(JoinPoint jp){
            String className = jp.getSignature().getDeclaringTypeName();
            String methodName = jp.getSignature().getName();
            System.out.print("正常返回Log:调用"+className+"的"+methodName+"方法,参数为:");
            for (Object obj : jp.getArgs()) {
                System.out.print(obj.toString());
            }
            System.out.println("");
        }
        /**
         * 抛出异常返回时调用
         * @param jp 调用点信息
         * @param ex 异常信息
         */
        @AfterThrowing(pointcut="execution(* site.zhanjingbo.service.*.*(..))",throwing="ex")
        public void logAfterThrowing(JoinPoint jp,Exception ex){
            String className = jp.getSignature().getDeclaringTypeName();
            String methodName = jp.getSignature().getName();
            System.out.print("异常Log:调用"+className+"的"+methodName+"方法,参数为:");
            for (Object obj : jp.getArgs()) {
                System.out.print(obj.toString());
            }
            System.out.println("。抛出异常:"+ex.getMessage()+"!");
        }
    }
    
  4. 编写模拟调用的Application类,来模拟业务。

    public class Application {
        public static void main(String[] args){
            //加载Spring相关配置文件
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
    
            //获取UserService实例
            UserService userService = applicationContext.getBean(UserService.class);
            //调用方法
            try {
                userService.add("ZhangSan");
            } catch (Exception e) {
    
            }
            //获取ProductService实例
            ProductService productService = applicationContext.getBean(ProductService.class);
            //调用方法
            productService.del("Pen");
    
            ((ConfigurableApplicationContext)applicationContext).close();
        }
    }
    

程序运行结果

Service的方法正常调用或调用异常结束后,完成对应的切面方法响应,输出对应的Log。