java技术--Spring AOP应用

使用SpringAop切面+自定义注解将日志记录存储到数据库的应用实例步骤:
1.配置applicationContext-mvc.xml

<mvc:annotation-driven />
<!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->
<context:component-scan base-package="com.gcx" /> 
<!-- 启动对@AspectJ注解的支持 -->
<!-- proxy-target-class等于true是强制使用cglib代理,proxy-target-class默认是false,如果你的类实现了接口 就走JDK代理,如果没有,走cglib代理 -->
<!-- 注:对于单利模式建议使用cglib代理,虽然JDK动态代理比cglib代理速度快,但性能不如cglib -->
<!--如果不写proxy-target-class="true"这句话也没问题-->
<aop:aspectj-autoproxy proxy-target-class="true"/> 
<!--切面-->
<bean id="systemLogAspect" class="com.gcx.annotation.SystemLogAspect"></bean>

2.创建日志类实体

1)日志分为:操作日志,系统日志
(2)操作日志:
public class OperationLog implements java.io.Serializable{
	private static final long serialVersionUID = 5509842054233533179L;
	@Id
	private Long id;
	/*
	 * 备注
	 */
	private String description;
	/*
	 * 操作名称
	 */
	private String name;
	/*
	 * 父模块名称
	 */
	private String parentName;
	/*
	 * URL
	 */
	private String url;
	/*
	 * 操作值
	 */
	private Float value;
	/*
	 * 操作类型
	 */
	private Integer category;
	/*
	 * 触发类型 0:触发前  1:触发后 2:异常
	 */
	private Integer triggerType;
	/*
	 * 操作日期
	 */
	private Date recordTime;
	/*
	 * 操作人
	 */
	private String operator;3)系统日志:
public class SystemLog implements java.io.Serializable{
	private static final long serialVersionUID = 8422381527159954814L;
	@Id
	private Long id;
	/*
	 * 备注
	 */
	private String description;
	/*
	 * 异常名称
	 */
	private String name;
	/*
	 * 异常内容
	 */
	private String content;
	/*
	 * 错误类型,如数据库、webservice等
	 */
	private String category;
	/*
	 * 异常日期
	 */
	private Date recordTime;

3.编写日志dao层,dao层实现类daoImpl,service层,service实现类serviceImpl,controller层

(1)到这里基本程序编写完毕

4.自定义系统日志注解

package com.gcx.annotation;
import java.lang.annotation.*;
@Target({ElementType.PARAMETER, ElementType.METHOD}) //定义注解的作用目标、范围字段、枚举常量、方法
@Retention(RetentionPolicy.RUNTIME) //注解会在class中存在,运行时可通过反射获取
@Documented //说明该注解将被包含在javadoc中
public @interface LogAnnotation {
  /** 要执行的操作类型比如:add操作 **/ 
  public String operationType() default ""; 
    
  /** 要执行的具体操作比如:添加用户 **/ 
  public String operationName() default "";
}

5.编写切面类

1)将切面的名称命名为:SystemLogAspect 
(2)这个类当中将声明各种通知,以及处理通知的方法
(3)调用Logservice来实现将记录的日志写入到数据库当中,用到的就是反射的方法
(4)下面是代码:
//这个类就是切面
@Aspect
//让其被Spring容器去管理
@Component
public class SystemLogAspect {
    //注入用于把日志保存数据库
    @Resource
	private OperationLogDAO operationLogDAO;
	@Resource
	private SystemLogDAO systemLogDAO;
   @Resource
   private UserDAO userDAO;
   //本地异常日志记录对象
  private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);
	// 指定切入点,拦截哪些方法,系统中所有执行操作方法的切点(注解其实就是切点)
	@Pointcut(value="@annotation(com.gcx.annotation.OperationLogger)")
	public void operationLogPoint(){}
	@Pointcut("execution(* com.gcx.annotation..*.*(..))")
	public void systemLogPoint() {}
	/** 
   * 前置通知 用于拦截记录用户的操作 
   * @param joinPoint 切点 
   * JoinPoint就是连接点,切点的实现方法就是通知
   */ 
    @Before("operationLogPoint()")
    public void before(JoinPoint joinPoint){
        System.out.println("我是前置通知");
          if(logger.isInfoEnabled()){
      logger.info("before " + joinPoint);
    }
    }
    
    @After("operationLogPoint()")
    public void After(JoinPoint joinPoint){
        System.out.println("我是后置通知");
         //去处理日志
       OperationLog log= new OperationLog();
       //控制日志是否记录,避免记录空日志
		Boolean isOK = true;
		try {
			//获取URL信息
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
			String url = request.getRequestURL().toString();
			String userId = request.getHeader("user");
			String userName = null;
			if(!userId.equals("-1")){
				userName = userDAO.getSingleUserByid(Long.parseLong(userId)).getName();
			}else{
				userName = "-1";
			}
			
			//被织入的目标对象(获取注解中对方法的描述信息)
			LogAnnotation annotationClass = point.getTarget().getClass().getAnnotation(LogAnnotation.class);
			String moduleName = annotationClass.moduleName();
			//操作名称
			Signature signature = point.getSignature();    
			MethodSignature methodSignature = (MethodSignature)signature;    
			Method targetMethod = methodSignature.getMethod(); 
			LogAnnotation annotationMethod = targetMethod.getAnnotation(LogAnnotation.class);
			String operationName = annotationMethod.operationName();
			if(operationName == null || operationName.isEmpty()){
				isOK = false;
			}
			//触发类型
			Integer triggerType = 0;
			log.setName(operationName);
			log.setParentName(moduleName);
			log.setUrl(url);
			log.setRecordTime(new Date());
			log.setTriggerType(triggerType);
			log.setOperator(userName);
			log.setDescription(userName+"准备执行操作"+operationName);
		} catch (SecurityException e) {
			isOK = false;
			recordSystemLog(e);
			e.printStackTrace();
		} finally{
			if(isOK){
			//保存数据库 
			operationLogDAO.saveLog(log);
			}
		}
    }
 
   @Around("operationLogPoint()")
   public void around(JoinPoint joinPoint){
     System.out.println("我是环绕通知");
     long start = System.currentTimeMillis();
     try {
       ((ProceedingJoinPoint) joinPoint).proceed();
       long end = System.currentTimeMillis();
       if(logger.isInfoEnabled()){
         logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
       }
       System.out.println("==========结束执行controller环绕通知===============");
     } catch (Throwable e) {
       long end = System.currentTimeMillis();
       if(logger.isInfoEnabled()){
         logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
       }
     }
   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值