`
Mr_White_b
  • 浏览: 1304 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java设计模式之JDK动态代理

    博客分类:
  • java
阅读更多
1、代理的概念
为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以
用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
     
          功能:负责请求的预处理、过滤、执行完请求后续处理,使得委托类专注于业务处理.SpringAOP就是采用的这种模式

A1、根据代理类的生成时间不同,分为静态代理和动态代理.此处所讲为JDK代理,主要运用java的反射机制
(1)所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
    Begin-------->生成步骤:   
       a首先业务接口 SubJect
       b然后委托类实现:RealSubject
       c再者:建立代理类,拥有一个委托类对象,然后重写方法,其中重写方法调用委托类的方法,并且可以做一些前置和后续处理
       d最后:建立代理对象的访问方式,一般是通过静态:static ProxyClass getInstance();
       End---------->
      
(2)动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。
         代理类和委托类的关系是在程序运行时确定。
    Begin-------->生成步骤:
    a. 实现InvocationHandler接口创建自己的调用处理器--->主要是对委托类的一些方法进行处理封装,其内部通常包含指向委托类
                 实例的引用,用于真正执行分派转发过来的方法调用 
   InvocationHandler handler = new InvocationHandlerImpl(..);  
    b. 给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类
   Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });  
    c. 以调用处理器类型为参数,利用反射机制得到动态代理类的构造函数
         Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });  
    d. 以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象
         Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler }); 
        其中:Proxy类的静态方法newProxyInstance对上面具体步骤的后三步做了封装,简化了动态代理对象的获取过程。
    a.InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发 
   InvocationHandler handler = new InvocationHandlerImpl(..);  
    b.通过 Proxy 直接创建动态代理类实例 
   Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,new Class[] { Interface.class },  handler );
    End---------->

(3)、优缺点比较:
  X1:静态代理类优缺点
  Advantage:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
  Disadvantage:
  a.代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
  b.如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
  X2:动态代理类优缺点
  Advantage:最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,
           在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。此处的外围业务类似类似Spring AOP
  Disadvantage:无法对Class进行动态代理,因为所有代理类有共同的父类:Proxy,由于不能进行多继承。
    
A2、另外一种常用代理为cglib代理,基于类的动态代理,cglib动态代理底层是借助asm来实现的,而asm在生成类之后的相关执行过程中比较高效
  (可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)
(1)
   Begin------------->生成步骤:
   a.需要实现MethodInterceptor接口,实现intercept方法。该代理中在委托类方法前后加入了自定义的切面逻辑,委托类方法的执行语句为:
     proxy.invokeSuper(object, args);
   b.获取增强的目标类的工厂Factory,其中增强的方法类对象是有Enhancer来实现的
     RealSubject realSubject = (RealSubject) enhancer.create(); 
   End------------->
  
(2) 
  cglib代理和jdk代理的区别:
  jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有
  一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
  相对来说,动态代理的实现更简单一些。
总结:
代理类和委托类都要去实现一个接口。以接口为桥梁实现代理。
代理类中设置接口为句柄属性,并提供setter方法。并构造一个带参(接口句柄)的构造器。覆盖接口中的方法中编写代理逻辑(之前或之后)。
测试---> 接口 接口句柄  =   new 代理类(new 委托类());

 
接口类
/**
 * 代理接口。处理给定名字的任务。
 */
public interface Subject {
	/**
	 * 执行给定名字的任务。
	 * @param taskName
	 *            任务名
	 */
	public void dealTask(String taskName);

	public void test2(String s);
}

委托类
/**
 * 真正执行任务的类,实现了代理接口。 也叫委托类
 */
public class RealSubject implements Subject {

	/**
	 * 执行给定名字的任务。这里打印出任务名,并休眠500ms模拟任务执行了很长时间
	 * @param taskName
	 */
	@Override
	public void dealTask(String taskName) {
		System.out.println("正在执行任务:" + taskName);
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void test2(String s) {
		System.out.println("123" + s);
	}
}

动态代理处理类
/**
 * 动态代理类对应的调用处理程序类
 */
public class SubjectInvocationHandler implements InvocationHandler {

	// 代理类持有一个委托类的对象引用
	private Object delegate;

	public SubjectInvocationHandler(Object delegate) {
		this.delegate = delegate;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		long stime = System.currentTimeMillis();
		// 利用反射机制将请求分派给委托类处理。Method的invoke返回Object对象作为方法执行结果。
		// 因为示例程序没有返回值,所以这里忽略了返回值处理 ,这里method类似于一个对所有方法的描述..
		Object object = method.invoke(delegate, args);
		long ftime = System.currentTimeMillis();
		System.out.println("执行任务耗时" + (ftime - stime) + "毫秒");
		return object;
	}
}

动态工厂及测试
/**
 * 生成动态代理对象的工厂.
 */
public class DynProxyFactory {
	// 客户类调用此工厂方法获得代理对象。
	// 对客户类来说,其并不知道返回的是代理类对象还是委托类对象。
	public static Subject getInstance() {
		Subject delegate = new RealSubject();
		// InvocationHandler相当于对某个指定对象所有方法包括构造器的一个封装,通过InvocationHandler可以指定调用哪个方法...
		InvocationHandler handler = new SubjectInvocationHandler(delegate);
		Subject proxy = null;
		// proxy = Proxy.newProxyInstance(loader, interfaces, h);
		proxy = (Subject) Proxy
				.newProxyInstance(delegate.getClass().getClassLoader(),
						delegate.getClass().getInterfaces(), handler);
		return proxy;
	}

	public static void main(String[] args) {
		// DynProxyFactory.getInstance().dealTask("DBQueryTask");
		DynProxyFactory.getInstance().test2("china");
		// Class cls = Proxy.getProxyClass(new
		// RealSubject().getClass().getClassLoader(), Subject.class);
		// System.out.println(cls.getName());
		// System.out.println(Proxy.isProxyClass(cls));
	}
}

测试结果
123china
执行任务耗时1毫秒

分享到:
评论

相关推荐

    JAVA设计模式在JDK中的应用

    ### JAVA设计模式在JDK中的应用 #### 一、引言 在软件开发过程中,设计模式作为一套被广泛接受的解决方案,能够帮助开发者解决常见的设计问题。Java作为一门流行的编程语言,其标准库(JDK)中巧妙地融入了多种设计...

    JDK动态代理_JDK动态代理

    在软件工程中,代理模式是一种常见的设计模式,它通过为一个对象提供一个替代品或占位符来控制对这个对象的访问。这种模式通常用于添加额外的功能(例如日志记录、事务管理等)而无需修改原始对象的实现。本文将详细...

    java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar

    java设计模式【之】JDK动态代理【源码】【场景:帮爸爸买菜】.rar /** * 代理模式 * 在开发者的角度来看,创建一个代理对象,提供给用户使用,避免用户直接访问真正的对象 * 在用户角度来看,就是普通的类方法...

    java常用设计模式及JDK与CGLIB实现动态代理区别(源码)

    java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...

    java jdk 动态代理 演示demo

    代理模式是一种设计模式,它提供一个代理类来控制对原对象的访问。在静态代理中,我们通过编写额外的代理类来实现这一目标,但在动态代理中,代理类是在运行时生成的,无需预先编写代码。 Java JDK提供了`java.lang...

    代理模式,JDK动态代理,SpringAOP来龙去脉

    代理模式是一种设计模式,它允许我们为一个对象创建一个代理对象,这个代理对象在客户端与目标对象之间起到中介的作用,可以增强或修改目标对象的行为,同时保持相同的接口。在Java中,我们可以使用JDK的动态代理...

    Java设计模式——代理设计模式(静态代理和动态代理)

    代理设计模式分为静态代理和动态代理两种类型。 ### 静态代理 静态代理是在编译时就已经确定了代理关系,代理类和真实类的关系是硬编码在代理类中的。下面我们将详细介绍静态代理的实现方式: 1. **定义接口**:...

    AOP之JDK动态代理和CGLib动态代理

    在Java世界中,面向切面编程(Aspect Oriented Programming,简称AOP)是一种设计模式,它允许程序员在不修改源代码的情况下,插入新的行为或增强已有功能。Spring框架是AOP实现的一个典范,它提供了两种主要的动态...

    JDK动态代理简单示例

    除了基本的代理实现,JDK动态代理还可以结合其他设计模式,如工厂模式,创建更加复杂的代理对象。此外,Spring框架中的AOP功能也是基于JDK动态代理或CGLIB实现的,它允许开发者定义切面,对满足特定条件的方法进行...

    java 动态代理实例(JDK代理与CGLIB代理)

    动态代理主要分为两种:JDK代理和CGLIB代理。 **JDK代理**是基于接口的代理,它通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。当我们的目标对象实现了特定的接口时,我们可以...

    java动态代理(JDK和cglib).pdf

    Java 动态代理是Java语言中的一个重要特性,它允许我们在...这在设计模式中被称为代理模式,对于构建复杂、模块化的系统具有重要作用。了解和熟练使用这两种动态代理技术,可以极大地提升Java开发的效率和代码质量。

    代理模式-静态动态代理-jdk动态代理-cglib动态代理

    代理模式是一种设计模式,它允许我们在不修改原有对象的情况下,为对象添加新的功能或行为。在Java中,代理模式有多种实现方式,包括静态代理、JDK动态代理和CGLIB动态代理。 **静态代理** 静态代理是最早也是最...

    Jdk动态代理和cglib动态代理原理

    Java中的动态代理是一种重要的设计模式,它允许在运行时创建具有特定行为的代理对象,以扩展或增强原有对象的功能。动态代理主要分为两种技术:JDK动态代理和CGLIB动态代理。 ### JDK动态代理 JDK动态代理是Java...

    静态代理、jdk动态代理、cglib动态代理

    JDK 动态代理是 Java 语言中的一种代理模式实现方式,它使用 Java 反射机制来实现代理对象的创建。在 JDK 动态代理中,我们不需要在编译时创建代理类,而是使用 Java 反射机制在运行时动态创建代理对象。 JDK 动态...

    java常用设计模式-代理模式

    Java 设计模式 - 代理模式 代理模式(Proxy Pattern)是一种常用的设计模式,提供了间接访问目标对象的一种方式,即通过代理对象访问目标对象。这样做的好处是,可以在不改变原有目标对象的基础上,对目标对象增加...

    Java设计模式-代理模式例子

    在这个“Java设计模式-代理模式例子”中,我们可能能看到如何创建静态代理类,以及如何利用`Proxy`和`InvocationHandler`创建动态代理。源码分析可以帮助我们更好地理解代理模式的实现细节,并能将其运用到自己的...

    jdk动态代理 + 拦截器实现小例

    在Java编程中,JDK动态代理是一种非常实用的技术,它允许我们在运行时创建代理类来增强或拦截原有类的方法调用。在这个“jdk动态代理 + 拦截器实现小例”中,我们将探讨如何利用Java的InvocationHandler接口和Proxy...

    JAVA设计模式(代理模式)

    **Java设计模式——代理模式详解** 代理模式是软件设计模式中的一个重要组成部分,它在Java编程中扮演着举足轻重的角色。代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象可以控制对原...

Global site tag (gtag.js) - Google Analytics