`

温习温习 aop的原理

阅读更多
在我工作这几年里,spring aop 用得最多的有两点

1  事务通过aop来配置
2  判断service 或者dao 层 运行时间

那么原理是怎么样的呢? 我也没有想去细致的理解

首先 我们想实现一个功能
请看如下的类:


packagecom.aop;
 
/**
 * Created with IntelliJ IDEA.
 * User: zhangyong
 * Date: 13-2-11
 * Time: 下午10:23
 * To change this template use File | Settings | File Templates.
 */
publicinterfaceIHello {
 
    publicvoidsayHello();
 
}
1111
实现类如下:

packagecom.aop.impl;
 
importcom.aop.IHello;
 
importjava.lang.reflect.Proxy;
 
/**
 * Created with IntelliJ IDEA.
 * User: zhangyong
 * Date: 13-2-11
 * Time: 下午10:24
 * To change this template use File | Settings | File Templates.
 */
publicclassIHelloImplimplementsIHello {
 
    @Override
    publicvoidsayHello() {
        System.out.println("Hello come on");
    }
 
 
 
}


2  添加代理类来绑定接口

   代理类首先 需要实现 InvocationHandler

   所以 定义个代理类


  

packagecom.aop;
 
importorg.apache.log4j.Logger;
 
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
importjava.lang.reflect.Proxy;
importjava.sql.Connection;
 
/**
 * hello的代理类
 * User: zhangyong
 * Date: 13-2-11
 * Time: 下午10:26
 * To change this template use File | Settings | File Templates.
 */
publicclassHelloProxyimplementsInvocationHandler {
 
    privatestaticLogger logger = Logger.getLogger(HelloProxy.class);
 
    privateIHello hello;
 
    publicHelloProxy(IHello hello) {
        this.hello = hello;
    }
 
    publicstaticIHello newInstance(IHello hello) {
        InvocationHandler handler =newHelloProxy(hello);
        ClassLoader classLoader = IHello.class.getClassLoader();
 
        return(IHello) Proxy.newProxyInstance(classLoader,newClass[]{IHello.class}, handler);
    }
 
    @Override
    publicObject invoke(Object proxy, Method method, Object[] args)throwsThrowable {
        logger.info("I am invoking starting");
        Object returnObj = method.invoke(hello, args);
        logger.info("I am invoking ending");
        returnreturnObj;
    }
 
 
}


ok ! 代理类写好了 我们需要写意个测试类 :


packagecom.aop;
 
importcom.aop.impl.IHelloImpl;
importorg.apache.commons.logging.Log;
importorg.apache.commons.logging.LogFactory;
 
importjava.sql.Connection;
 
/**
 * 测试aop
 * User: zhangyong
 * Date: 13-2-11
 * Time: 下午10:25
 * To change this template use File | Settings | File Templates.
 */
publicclassTestAop {
 
    privatestaticfinalLog log = LogFactory.getLog(Connection.class);
 
    publicstaticvoidmain(String[] args) {
        IHello hello = HelloProxy.newInstance(newIHelloImpl());
        hello.sayHello();
    }
 
}



运行结果如下:

2013-02-15 17:26:18,844  INFO main com.aop.HelloProxy:invoke(36) - I am invoking starting
Hello come on
2013-02-15 17:26:18,847  INFO main com.aop.HelloProxy:invoke(38) - I am invoking ending


另外在mybatis 里 当我们在log4j里配置好 输出的时候 比如:

log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG


就会打印响应的sql ,在mybatis里 涉及到的类是: ConnectionLogger



package org.apache.ibatis.logging.jdbc;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.reflection.ExceptionUtil;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;

/**
 * Connection proxy to add logging 添加日志的代理(好方法)
 */
public class ConnectionLogger extends BaseJdbcLogger implements InvocationHandler {

  private static final Log log = LogFactory.getLog(Connection.class);

  private Connection connection;

  private ConnectionLogger(Connection conn) {
    super();
    this.connection = conn;
    if (log.isDebugEnabled()) {//在log4j中配置
      log.debug("ooo Connection Opened");
    }
  }

  public Object invoke(Object proxy, Method method, Object[] params)
      throws Throwable {
    try {
      if ("prepareStatement".equals(method.getName())) {
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
        stmt = PreparedStatementLogger.newInstance(stmt, (String) params[0]);
        return stmt;
      } else if ("prepareCall".equals(method.getName())) {
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
        stmt = PreparedStatementLogger.newInstance(stmt, (String) params[0]);
        return stmt;
      } else if ("createStatement".equals(method.getName())) {
        Statement stmt = (Statement) method.invoke(connection, params);
        stmt = StatementLogger.newInstance(stmt);
        return stmt;
      } else if ("close".equals(method.getName())) {
        if (log.isDebugEnabled()) {
          log.debug("xxx Connection Closed");
        }
        return method.invoke(connection, params);
      } else {
        return method.invoke(connection, params);
      }
    } catch (Throwable t) {
      Throwable t1 = ExceptionUtil.unwrapThrowable(t);
      log.error("Error calling Connection." + method.getName() + ':', t1);
      throw t1;
    }

  }

  /**
   * Creates a logging version of a connection
   *
   * @param conn - the original connection
   * @return - the connection with logging
   */
  public static Connection newInstance(Connection conn) {
    InvocationHandler handler = new ConnectionLogger(conn); 
    ClassLoader cl = Connection.class.getClassLoader();
    return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
  }

  /**
   * return the wrapped connection
   *
   * @return the connection
   */
  public Connection getConnection() {
    return connection;
  }

}


它的调用方式是:

/** 根据日志级别 封装connection 若是DEBUG级别 则封装log **/
private Connection wrapConnection(Connection connection) {
  if (log.isDebugEnabled()) {
    return ConnectionLogger.newInstance(connection);
  } else {
    return connection;
  }
}
分享到:
评论
1 楼 pp_wen 2013-05-17  
求楼主头像原图 372791833@qq.com

相关推荐

    spring aop实现原理

    NULL 博文链接:https://zhang-yingjie-qq-com.iteye.com/blog/319927

    Spring AOP面向方面编程原理:AOP概念

    ### Spring AOP面向方面编程原理:AOP概念详解 #### 一、引言 随着软件系统的日益复杂,传统的面向对象编程(OOP)...对于希望深入了解Spring AOP原理与实践的读者来说,掌握以上概念将是开启面向方面编程之旅的第一步。

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    面向切面编程(AOP)是一种编程范式,旨在将横切关注点(如日志、安全等)与业务逻辑分离,从而提高模块化。AOP通过预定义的“切面”对横切关注点进行模块化,从而可以在不修改业务逻辑代码的情况下增加新功能。动态...

    代理机制及AOP原理实现

    本文将深入探讨这两个主题,并结合JDK的反射和CGLIB库来阐述其实现原理。 首先,我们来看动态代理。动态代理是Java提供的一种在运行时创建代理对象的技术,它允许我们在不修改原有代码的情况下,为已有接口添加额外...

    aop.zip_884AOP_java aop原理_javaaop原理

    Java AOP(面向切面编程)是软件设计中的一个重要概念,它允许程序员定义“切面”,这些切面封装了特定的、与业务逻辑不直接相关的关注点,如日志、事务管理、性能监控等。AOP的核心思想是将横切关注点从核心业务...

    spring ioc和aop原理流程图(详细)

    Spring 框架是Java开发中的核心框架,它主要由两个关键部分组成:IOC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。这两个概念是Spring框架的核心特性,极大地简化了企业...

    使用动态代理演示Spring的AOP编程原理

    为了说明Spring的AOP原理,本人使用代理模式中的动态代理完成演示AOP编程的原理的演示。相信,如果你耐心看完整个程序(几乎一行注释一行代码),那么你对Spring这个东西就不是觉得有什么神秘了! 阅读对象:凡是喜爱...

    aop的工作原理

    **AOP(面向切面编程)**是一种编程范式,主要应用于处理系统中的横切关注点,例如日志记录、事务管理、权限控制等。它将这些分散在代码各处的功能抽取出来,集中管理和实现,使得核心业务逻辑更加清晰。 在Java中...

    代理模式与动态代理--Spring AOP原理.doc

    代理模式与动态代理--Spring AOP原理.doc

    Spring 框架之 AOP 原理剖析 - GitChat

    Spring 框架之 AOP 原理剖析.html 抓下来打包成了HTML文件, 方便离线观看

    Java动态代理(Spring Aop原理)

    在Spring框架中,AOP(面向切面编程)就是基于Java动态代理来完成的,用于实现横切关注点,如日志、事务管理等。这篇博客的文章链接虽然没有给出具体内容,但我们可以根据Java动态代理和Spring AOP的基本概念来深入...

    Spring Aop的底层实现技术 --- Jdk动态代理原理

    Spring AOP 的底层实现技术 --- Jdk 动态代理原理 JDK 动态代理是 Spring AOP 的底层实现技术,允许开发者在运行期创建接口的代理实例。在 JDK 1.3 以后,JDK 动态代理技术提供了实现 AOP 的绝好底层技术。JDK 动态...

    aop原理使用demo

    本"AOP原理使用demo"是针对AOP编程的一个实例展示,通过这个示例,我们可以深入理解AOP的核心概念和在实际应用中的使用方式。以下是对AOP关键概念的详细解释: 1. **切面(Aspect)**:切面是AOP的核心,它封装了横...

    JDK动态代理 spring aop 的原理

    现在让我们深入探讨JDK动态代理和Spring AOP的原理。 首先,JDK动态代理基于Java的反射机制,通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,...

    Spring AOP实现机制

    **Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...

    反射实现 AOP 动态代理模式(Spring AOP 的实现 原理) - Java 例子 -

    本文将深入探讨Spring AOP的实现原理,以及如何使用反射来实现动态代理模式。 首先,我们需要了解AOP的基本概念。AOP的核心思想是切面,它包含两个主要部分:切点(Pointcut)和通知(Advice)。切点定义了在程序...

    spring aop 原理解析

    【Spring AOP 原理解析】 Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许开发者定义“切面”来封装系统中的交叉关注点,如日志、事务管理、安全性等,从而提高代码的可复用性和可维护性。在Spring ...

    spring aop spring aop

    在给出的XML配置中,`<aop:config>`元素开启AOP支持,而`<aop:aspect>`元素用于定义切面,其内部通过`<aop:pointcut>`定义切点,并通过`<aop:before>`和`<aop:after>`指定通知。 为了使用这些配置,我们需要在代码...

    AOP实现原理.jpg

    java AOP实现原理.jpg

Global site tag (gtag.js) - Google Analytics