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

Java设计模式之cglib动态代理

    博客分类:
  • 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 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);
	}
}

cglib代理类
/**
 * 此为代理类,用于在pointcut处添加advise
 * 
 */
public class CglibProxyHandler implements MethodInterceptor {

	public Object intercept(Object object, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		// 添加切面逻辑(advise),此处是在目标类代码执行之前,即为MethodBeforeAdviceInterceptor。
		System.out.println("before-------------");
		// 执行目标类方法
		proxy.invokeSuper(object, args);
		// 添加切面逻辑(advise),此处是在目标类代码执行之后,即为MethodAfterAdviceInterceptor。
		System.out.println("after--------------");
		return null;
	}
}

工厂类
/**
 * 工厂类,生成增强过的目标类(已加入切入逻辑)
 * @author Guobaoqiang
 */
public class CglibProxyFactory {
	/**
	 * 获得增强之后的目标类,即添加了切入逻辑advice之后的目标类
	 * 
	 * @param proxy
	 * @return
	 */
	public static RealSubject getInstance(CglibProxyHandler proxy) {
		Enhancer enhancer = new Enhancer();
		// 注意这儿的参数是个关键,是基于委托类的对象,而不是接口对象
		enhancer.setSuperclass(RealSubject.class);
		// 回调方法的参数为代理类对象CglibProxyhandler,最后增强目标类调用的是代理类对象CglibProxyhandler中的intercept方法
		enhancer.setCallback(proxy);
		// 此刻,subject不是单纯的目标类,而是增强过的目标类
		RealSubject subject = (RealSubject) enhancer.create();
		return subject;
	}
}

测试
public class Client {
	public static void main(String[] args) {
		Subject proxy = CglibProxyFactory.getInstance(new CglibProxyHandler());
		proxy.dealTask("DBQueryTask");
	}
}

测试结果
before-------------
正在执行任务:DBQueryTask
after--------------
分享到:
评论

相关推荐

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

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

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

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

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

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

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

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

    jdk与cglib动态代理与底层实现

    在Java编程领域,代理模式是一种常见且重要的设计模式,它允许我们为一个对象提供一个代理以控制对该对象的访问。代理模式在实际应用中广泛用于数据缓存、权限控制、事务处理等方面。JDK和CGLIB是Java中实现动态代理...

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

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

    CgLib动态代理所需的jar

    设计模式方面,CgLib动态代理与工厂模式、装饰器模式和代理模式有关。在AOP中,CgLib实际上扮演了代理的角色,创建了一个目标对象的代理,允许在调用实际方法前后添加额外的行为。这种行为类似于装饰器模式,因为它...

    基于MAVEN项目的CGLib动态代理原理及实现

    在Java编程领域,动态代理是一种常见的设计模式,它允许我们在运行时创建代理对象来扩展或增强已有对象的功能。本文将深入探讨如何在基于Maven的项目中利用CGLib库实现动态代理。CGLib(Code Generation Library)是...

    Java JDK代理、CGLIB、AspectJ代理分析比较

    代理模式是一种常见的设计模式,在《Design Patterns in Java》一书中对其有明确的定义:“代理模式为一个对象提供一个代理,以控制对该对象的访问。”简而言之,代理模式允许我们在不修改原始类的情况下,通过引入...

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

    Cglib 动态代理的优点是:它的实现方式高效灵活,可以在运行时动态创建代理对象,并且不需要使用 Java 反射机制。但是,它的缺点是:它需要使用 Cglib 库,该库可能增加系统的复杂度。 代理模式的应用场景 代理...

    JAVA JDK静态代理、动态代理、CGlib代理的代码演示

    在Java编程中,代理模式是一种常用的面向对象设计模式,它允许我们为一个对象提供一个代理以控制对该对象的访问。代理模式在很多场景下都非常有用,例如在远程调用、安全控制、日志记录等。Java提供了两种主要的代理...

    Java动态代理详解; CGLib实现动态代理1

    在 Java 中,代理模式是一种设计模式,它允许我们在不修改原有对象的基础上,为对象增加额外的功能。代理模式的核心在于代理类(Proxy)作为真实对象(RealSubject)的替代品,提供与真实对象相同的接口,但在调用...

    Java动态代理(JDK和cglib)

    代理模式是一种结构型设计模式,其中代理类含有一个对真实主题对象的引用,这样代理对象就可以执行一些预备或清理工作,并将真正的调用传递给真实主题对象。 在Java中,代理模式的应用非常广泛,特别是在框架级开发...

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

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

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

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

    cglib代理模式要使用的相关jar包

    在Java编程中,代理模式是一种设计模式,它允许我们在不修改原有对象的基础上,为对象添加新的功能或行为。代理模式通常分为静态代理和动态代理。本文将重点介绍使用CGLIB库实现的动态代理。 CGLIB(Code ...

    使用cglib演示动态代理时用到的jar包 aop 动态代理

    在Java编程领域,AOP(Aspect Oriented Programming,面向切面编程)是一种强大的设计模式,它允许程序员在不修改原有代码的情况下,通过插入新的行为来扩展功能。动态代理是实现AOP的一种方式,而在Java中,CGLIB...

    jdk与cglib动态度代理的区别原理

    在Java编程领域,动态代理是一种常见的设计模式,用于在运行时创建对象的代理,以便在调用实际目标方法之前或之后插入额外的行为。主要存在两种常见的动态代理技术:JDK动态代理和CGLIB(Code Generation Library)...

    CGLib代理模式用到的jar包

    在Java世界里,代理模式是一种常见的设计模式,它允许我们创建对象的代理来控制对原对象的访问。CGLib是Java中实现动态代理的一种方式,尤其是在Spring AOP(面向切面编程)中被广泛应用。 CGLib代理主要分为两种...

Global site tag (gtag.js) - Google Analytics