Spring AOP初级入门-代码篇之XML

介绍两种实现Spring AOP的代码。xml和@Aspectj注解

XML篇

此切面类中有一些方法在测试时可以

ApplicationContext.xml文件配置Spring相关信息
注意的就是xmlns:引用AOP的头部

<?xml version="1.0" encoding="UTF-8"?>
<!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ -->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/aop   
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd   
        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/mvc   
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd   
        ">
    <!-- 利用Schema-based(xml配置)实现 AOP 用到的配置都放在aop:config标签里  start by lily 2015-12-18 -->
    <aop:config>
        <!-- 配置Aspect(切面类) -->
        <aop:aspect id="myAspect" ref="logAspect">
            <!-- 配置Pointcut(切入点),表示此路径下的所有类的方法全部可以切入 -->
            <aop:pointcut id="logServer" expression="execution(* com.udbac.controller.*Controller.*(..))" />
            <!-- 配置advice(通知) ,此通知中所有的method都需要在切面类(LogAspectN.java)中一一对应   stard -->
            <aop:before method="before" pointcut-ref="logServer"/><!-- 前置通知 -->
            <aop:after-returning method="afterReturning" pointcut-ref="logServer"/><!-- 后置通知 -->
            <!--还可配置异常通知,环绕通知,这里不具体写了-->
            <!-- 配置advice end -->
        </aop:aspect>

    </aop:config>
    <!--AOP  使用的切面类 -->
    <bean id="logAspect" class="com.udbac.util.aop.LogAspectN"></bean>
    <!-- AOP 用到的配置  end -->
</beans>

LogAspectN.java 切面类
本类中可以将所有执行* com.udbac.controller.Controller.(..)此路径下的类的方法全部切入进来

package com.udbac.util.aop;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.udbac.service.LogService;

/***
 * Log切面类 ,使用配置XML方式
 * 
 * @date 2015-12-21
 * @author lily
 *
 */

public class LogAspectN {

    /**
     * 日志管理 接口,此接口的实现类并没有实现其他业务,如果存在业务写在实现类即可。
     */
    @Autowired(required = true)
    private LogService logService;
    /***
     * 前置通知
     * before对应ApplicationContext.xml中的<aop:before method="before" pointcut-ref="logServer"/><!-- 前置通知 -->
     * method名称一定要对应上
     */
    public void before() {
        System.out.println("前置通知!!!");
    }

    /***
     * 后置通知
     */
    public void afterReturning(JoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();

        // 请求的IP
        String ip = request.getRemoteAddr();
        try {
            // *========控制台输出=========*//
            System.out.println("=====后置通知开始=====");
            //方法名称
            String methodName=joinPoint.getTarget().getClass().getName() + "."
                    + joinPoint.getSignature().getName() + "()";
            //方法描述
            String s_function=getControllerMethodDescription(joinPoint);

            //操作内容
            String opContent = adminOptionContent(joinPoint.getArgs(), methodName);

            System.out.println("请求方法:"+ methodName);
            System.out.println("操作模块(方法描述):"+ s_function);
            System.out.println("操作内容:"+ opContent);
            //创建日志对象
            com.udbac.model.Log log = new com.udbac.model.Log();
            log.setUserid(logService.loginUserId());//设置管理员id
            log.setParameter(opContent);//参数
            log.setIp(ip);//ip
            log.setMethod(methodName);//请求方法
            log.setModule(s_function);//操作模块
            log.setOperation("查询");//操作

            //调用log日志接口,向数据库中增加日志数据
            logService.inserlog(log);//添加日志
        } catch (Exception ex) {

        }
    }

     /**  
     * 获取注解中对方法的描述信息 用于Controller层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    //获取controller注解中的 name,Log是我在调用controller方法前注解的Log。此处Log可以替换成其他。
                    description = method.getAnnotation(Log. class).name();    
                     break;    
                }    
            }    
        }    
         return description;    
    }  

     /**
     * 使用Java反射来获取被拦截方法(insert、update)的参数值,
     * 将参数值拼接为操作内容
     */
    public String adminOptionContent(Object[] args, String mName) throws Exception{

        if (args == null) {
            return null;
        }

        StringBuffer rs = new StringBuffer();
        rs.append(mName);
        String className = null;
        int index = 1;
        // 遍历参数对象
        for (Object info : args) {

            //获取对象类型
            className = info.getClass().getName();
            className = className.substring(className.lastIndexOf(".") + 1);
            rs.append("[参数" + index + ",类型:" + className + ",值:");

            // 获取对象的所有方法
            Method[] methods = info.getClass().getDeclaredMethods();

            // 遍历方法,判断get方法
            for (Method method : methods) {

                String methodName = method.getName();
                // 判断是不是get方法
                if (methodName.indexOf("get") == -1) {// 不是get方法
                    continue;// 不处理
                }

                Object rsValue = null;
                try {

                    // 调用get方法,获取返回值
                    rsValue = method.invoke(info);

                    if (rsValue == null) {//没有返回值
                        continue;
                    }

                } catch (Exception e) {
                    continue;
                }

                //将值加入内容中
                rs.append("(" + methodName + " : " + rsValue + ")");
            }

            rs.append("]");

            index++;
        }

        return rs.toString();
    }
}

LogService.java接口
LogService类就是在LogAspectN 类中 引用的接口
例如,在LogAspectN.java中有如下代码:
@Autowired(required = true)
private LogService logService;

package com.udbac.service;

import com.udbac.model.Log;
/**
 * 日志记录业务逻辑接口
 */
public interface LogService {

    /**
     * 日志记录
     * @param log
     */
    public void inserlog(Log log);

    /**
     * 获取登录管理员ID
     */
    public Long loginUserId();
}

LogServiceImpl.java实现类

package com.udbac.service.impl;
import org.springframework.beans.factory.annotation.Autowired;

import com.udbac.service.LogService;
import com.udbac.dao.LogMapper;
import com.udbac.model.Log;

/**
 * 日志记录业务逻辑接口实现类
 * @date 2015-12-18
 * @author lily
 */
public class LogServiceImpl implements LogService{


    /***
     * 由于使用的是MyBatis + Spring MVC结构,这里需要引用MyBatis使用interface 
     */
    @Autowired
    private LogMapper logMapper;

    public void inserlog(Log log) {

        logMapper.insert(log);//调用SQL,sql使用了MyBatis,所以也给insert方法提供了interface
        //在实现类里可以处理其他具体业务,这里只做一个测试输出
        System.out.println("增加日志具体业务!!!!+++++++++++++++++++++++");
    }

    @Override
    public Long loginUserId() {
        // TODO Auto-generated method stub
        return null;
    }



}

其实,在这里大部分Spring AOP的代码已经写完了,至于入库的部分为了以后自己参考也拿出来方便以后查看

LogMapper.java(处理SQL的接口)
本类中的insert()方法正是LogServiceImpl 类中调用的logMapper.insert(log)

package com.udbac.dao;

import com.udbac.model.Log;

/**
 * 日志记录Mapper
 * 
 * @date 2015-12-18
 * @author lily
 *
 */
public interface LogMapper {

    /****
     * 添加系统操作日志
     * @author lily
     * @date 2015-12-18
     * @param log
     */
    public void insert(Log log);
}

LogMapper.xml (Mybatis中的SQL)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.udbac.dao.LogMapper">
    <!-- 添加日志记录 -->
<!--    <select id="select">
    select * from tb_virp_system_log();
    </select> -->
    <insert id="insert" parameterType="map">
        INSERT INTO tb_virp_system_log(user_id,create_date,module,method,actions,ip,parameter)
        VALUES(#{userid},to_char(now(),'yyyy-mm-dd hh24:hh:ss')::timestamp,#{module},#{method},#{operation},#{ip},#{parameter});
    </insert>  
</mapper>

使用XML的方式实现AOP大概就是如此,主要在ApplicationContext.xml文件配置以及对应的切面类(LogAspectN )。只要能切入进来,调用相关的业务方法就简单了

下一篇将介绍使用@Aspectj注解方式实现Spring AOP。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值