`
seastar09
  • 浏览: 16668 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

spring中的AOP(代理对象)

阅读更多
在一个服务的流程中插入与业务逻辑无关的系统服务逻辑(如logginng,security),这样的逻辑称为cross-cutting concerns,将cross-cutting concerns独立出来设计为一个对象,这样的特殊对象称为Aspect,Aspect-oriented programming着重在Aspect的设计及与应用程序的织入(Weave)。
spring实现aop的方式之一是代理机制:
例如:当执行某些方法时候需要记录日志:一般这么写:
public class HelloSpeak(){
      private logger = Logger.getLogger(this.getClass().getName());
      public void sayHello(){
           logger.log(Level.Info,"begin");
           system.out.println("zzheng zai zhi xing");
           logger.log(Level.Info,"end");
      }
}
对于HelloSpeaker来说,记录日志的方法不是他的业务逻辑,这么做增加了他额外的职责,如果很多类都这么做,程序会很混乱。特别是还有其他的职能:如事务检查,安全处理,权限检查等。
    可以使用代理(Proxy)机制来解决这个问题,在这边讨论两种代理方式:静态代理(Static proxy)与动态代理(Dynamic proxy)。
静态代理
在静态代理的实现中,代理对象与被代理的对象都必须实现同一个接口,在代理对象中可以实现日志记录等相关服务,并在需要的时候再呼叫被代理的对象,如此代理对象当中就可以仅保留业务相关职责。举个实际的例子来说,首先定义一个IHello接口:
package aop;

public interface Ihello {
public void sayHello();
}
然后让实现业务逻辑的HelloSpeaker类实现IHello接口,例如:
package aop;

public class HelloSpeak implements Ihello {

public void sayHello() {
System.out.println("ni hao.");

}

}
在HelloSpeaker类中现在没有任何记录的程序代码插入其中,日志记录服务的实现将被放至代理对象之中,代理对象同样也要实现IHello接口,例如
public class HelloProxy implements Ihello {

private Logger logger = Logger.getLogger(this.getClass().getName());
private Ihello hellotest;

public HelloProxy(Ihello hellotest) {
this.hellotest = hellotest;
}

public void sayHello() {
log("begin ************");
hellotest.sayHello();
System.out.println("****" + logger);
log("end **********");
}

private void log(String msg) {
logger.log(Level.INFO, msg);
}
}

测试类如下:
public class Test {

/**
* @param args
*/
public static void main(String[] args) {
HelloSpeak hs = new HelloSpeak();
HelloProxy hp = new HelloProxy(hs);
hp.sayHello();
}

}
代理对象的一个接口只服务于一种类型的对象,而且如果要代理的方法很多,势必要为每个方法进行代理,静态代理在程序规模稍大时就无法胜任。

动态代理
在JDK1.3之后加入了可协助开发动态代理功能的API,您不必为特定对象与方法编写特定的代理对象,使用动态代理,可以使得一个处理者(Handler)服务于各个对象。首先,一个处理者的类设计必须实现java.lang.reflect.InvocationHandler接口,以实例来进行说明,例如设计一个LogHandler类
package dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LogHandler implements InvocationHandler {
private Logger log = Logger.getLogger(this.getClass().getName());

private Object delegate;
public Object bind(Object delegate){
this.delegate = delegate;
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
this.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
try{
log("begin *********"+method);
result = method.invoke(delegate, args);
log("end *****"+method);
}catch(Exception e){
log(e.toString());
}

return result;
}
private void log(String msg){
log.log(Level.INFO,msg);
}

}
主要的概念是使用Proxy .newProxyInstance ()静态方法建立一个代理对象,建立代理对象时必须告知所要代理的接口,之后您可以操作所建立的代理对象,在每次操作时会执行InvocationHandler的invoke()方法,invoke ()方法会传入被代理对象的方法名称与执行参数,实际上要执行的方法交由method.invoke(),您在method.invoke()前后加上记录动作,method.invoke ()传回的对象是实际方法执行过后的回传结果。要实现动态代理,同样必须定义所要代理的接口,例如
package dynamic;

public interface Ihello {
public void sayHello();
}
然后让实现业务逻辑的HelloSpeaker类实现IHello接口,例如:
public class HelloSpeak implements Ihello {

public void sayHello() {
System.out.println("ni hao.");

}

}
编写一个测试的程序,您要使用LogHandler的bind ()方法来绑定被代理对象,如下所示:
public class Test {

/**
* @param args
*/
public static void main(String[] args) {
LogHandler lh = new LogHandler();
HelloSpeak ee = new HelloSpeak();
Ihello tt = (Ihello) lh.bind(ee);
tt.sayHello();
}

}
LogHandler不再服务于特定对象与接口,而HelloSpeaker也不用插入任何有关于记录的动作,它不用意识到记录动作的存在。
以上例子中,HelloSpeake本身的职责是显示招呼文字,却必须插入记录(Log)动作,这使得HelloSpeaker 的职责加重,在 AOP的术语来说,记录的程序代码横切(Cross-cutting)入HelloSpeaker的程序执行流程中,记录这样的动作在AOP中称之为横切关切点 (Cross-cutting concern)。
使用代理对象将记录等与业务逻辑无关的动作或任务提取出来,设计为一个服务对象,像是之前范例中示范的HelloProxy或是LogHandler,这样的对象称之为切面(Aspect)。
AOP中的Aspect所指的可以像是记录等这类的动作或服务,您将这些动作(Cross-cutting concems)设计为通用、不介入特定业务对象的一个职责清楚的Aspect对象,这就是所谓的Aspect-oriented programming,缩写名词即为 AOP 。
在好的设计之下, Aspect可以独立于应用程序之外,在必要的时候,可以介入应用程序之中提供服务,而不需要相关服务的时候,又可以将这些Aspect直接从应用程序中脱离,而应用程序本身不需修改任何一行程式码。
分享到:
评论

相关推荐

    死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序.pdf

    死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序

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

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

    Spring框架+SpringAOP动态代理

    SpringAOP动态代理 Spring AOP 使用的动态代理主要有两种方式:JDK 动态代理和 CGLIB 代理。 JDK 动态代理:用于代理实现了接口的类。Spring 会使用 java.lang.reflect.Proxy 类来创建代理对象。 CGLIB 代理:用于...

    spring_aop之JDK的动态代理

    基于JDK的动态代理。必须是面向接口的,只有实现了具体接口的类才能生成代理对象

    spring_aop4.rar_Home Home_jar 转换_spring AOP jar

    1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间...

    Spring  AOP实现方法大全

    在Spring1.2或之前的版本中,实现AOP的传统方式就是通过实现Spring的AOP API来定义Advice,并设置代理对象。Spring根据Adivce加入到业务流程的时机的不同,提供了四种不同的Advice:Before Advice、After Advice、...

    springAOP之代理模式.docx

    springAOP指的是在spring中的AOP,什么是AOP,相对于java中的面向对象(oop),在面向对象中一些公共的行为,像日志记录,权限验证等如果都使用面向对象来做,会在每个业务方法中都写上重复的代码,造成代码的冗余。...

    Spring实现AOP的四种方式

    2. 配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从容器中获得的其实已经是代理对象 3. 通过<aop:config>来配置(纯POJO切面) 4. 通过<aop: aspectj-autoproxy>来配置,使用AspectJ的注解...

    GenweiWu#Blog#spring aop代理1

    Spring AOP 代理一、两种代理方式1. JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。二

    spring_aop_cglib的实现方式

    如果想使用CGLIB的技术来生成代理对象,那么需要引入CGLIB的开发的jar包,在Spring框架核心包中已经引入了CGLIB的开发包了。所以直接引入Spring核心开发包即可!

    Spring AOP详细介绍.docx

    一 AOP的基本概念 (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知 (2)JointPoint(连接点):程序执行过程中明确的点,...Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

    SpringAOP的实现机制(底层原理)、应用场景等详解,模拟过程的实例

    您将了解如何使用Java的反射机制来创建代理对象,以及如何将横切逻辑注入到目标方法中。我们还提供了实际示例,演示如何在Spring AOP中使用JDK动态代理。 CGLib动态代理: 我们将深入研究CGLib动态代理,它允许您在...

    spring aop 实现源代码--xml and annotation(带lib包)

    在Spring1.2或之前的版本中,实现AOP的传统方式就是通过实现Spring的AOP API来定义Advice,并设置代理对象。Spring根据Adivce加入到业务流程的时机的不同,提供了四种不同的Advice:Before Advice、After Advice、...

    在Spring AOP代理过的对象上支持dubbo annotation配置事物失效问题-附件资源

    在Spring AOP代理过的对象上支持dubbo annotation配置事物失效问题-附件资源

    Spring AOP源码深度解析:掌握Java高级编程核心技术

    动态代理是实现AOP的基础,它通过JDK动态代理或CGLIB代理生成被代理对象的子类。通知是织入到目标对象连接点上的一段程序,例如@Before、@After等。 切点定义了通知应该在哪些连接点上触发。而切面则是通知和切点的...

    spring第五天 .pdf

    6. 源码阅读之产生AOP代理对象的流程 7. 代理对象执行流课程目标 1. 重点掌握aop底层的原理之动态代理机制的概述及差别 1. 重点掌握代理对象执行逻辑分析 2. 重点掌握Cglib代理技术之产生代理对象和代理对象执行逻辑...

    spring ioc.aop

    spring 的aop的详解如:切面,连接点,通知,切入点,目标对象,代理对象及annotation方式的aop实现和xml方式的事务管理等

    深入解析Spring AOP源码:从原理到实现,全方位掌握Java AOP编程精髓

    Spring AOP主要基于动态代理模式,它允许开发者在不改变原有代码结构的情况下,增加额外的行为。这主要通过定义“切面(Aspects)”和“通知(Advices)”来实现,其中切面定义了何时以及如何插入额外的行为,而通知...

    Spring AOP与动态代理

    Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。...

Global site tag (gtag.js) - Google Analytics