`

jdk动态代理和CGlib动态代理

阅读更多

Jdk动态代理,CGLib字节码生成

如果目标对象实现了接口,可以使用jdk动态代理和CGLib

如果没有实现接口,只能使用CGLib

一,jdk动态代理

1.java动态代理用到了一个类(Proxy)和一个接口(InvocationHandler)

2.jdk动态代理是通过实现目标类所实现的接口来产生代理类并生成代理对象的

3.类Proxy:该类用于创建目标类的代理对象。

Proxy类常用的方法有:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) 

该方法是一个static的方法,用于返回目标对象的代理对象

1.参数loader就是加载目标类的classloader

2.参数interfaces就是目标类所实现的接口

3.参数handler,就是接口InvocationHandler实现类的对象,我们要自己去实现该接口,

    并实现其方法Object  invoke(Object proxy, Method method, Object[] args) 

4.InvocationHandler用官方话说就是:是代理实例的调用处理程序 实现的接口

用我的话来说就是,代理对象调用某个方法时,就会调用handler的invoke方法,

该方法中拥有目标对象的引用,而且该方法中拥有权限判断等需要在目标方法被调用之前或之后进行的操作

在该方法中,会先进行权限判断,然后再真真正正的去调用目标对象对应的方法

5.要实现动态代理,首要条件是目标类是面向接口的

核心代码:

InvocationHandler:

package com.test.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler{
	//target就是目标对象  
    private Object target;   
    public void setObject(Object target) {  
        this.target = target;  
    } 
    
    //proxy就是代理对象  
    //method就是对应于在代理对象上调用的接口方法的 Method 实例,调用method.invoke()方法时才真真的去调用目标类的方法  
    //args是要往目标方法中传入的参数,一般来源于代理对象调用方法时传入的参数  
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		//method.getName()可以返回要调用的目标方法的名称  
        System.out.println("---------------目标方法:"+method.getName()+"执行之前do some thing---------------------");  
        //调用目标类的目标方法,returnObj是目标方法返回的值  
        Object returnObj = method.invoke(target, args);  
        System.out.println("---------------目标方法:"+method.getName()+"执行之后do some thing---------------------");  
          
        return returnObj;  
	}

}

 proxy:获取代理对象

package com.test.dynamicProxy;

import java.lang.reflect.Proxy;

public class GetProxyObj {
	private Object obj;  
    private MyInvocationHandler handler;  
    public GetProxyObj(Object obj,MyInvocationHandler handler){  
        this.obj = obj;  
        handler.setObject(obj);  
        this.handler = handler;  
    }  
    
    /**
     * 用于返回目标对象的代理类  
     * @return
     */
    public Class getProxyClass(){
        //obj.getClass().getClassLoader() 返回目标对象的classloader  
        // obj.getClass().getInterfaces()返回目标类所实现的接口数组  
        Class clazz = Proxy.getProxyClass(obj.getClass().getClassLoader(), obj.getClass().getInterfaces());  
        return clazz;  
    }  
    
    /**
     * 用于返回目标对象的代理对象  
     * obj.getClass().getClassLoader() 返回目标对象的classloader  
     * obj.getClass().getInterfaces()返回目标类所实现的接口数组  
     * @return
     */
    public Object getProxyObject(){  
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);  
    } 
}

 二,CGlib动态代理

cglib是Spring、Hibernate依赖的核心包,

但是cglib还算不上最底层的,因为它是在asm包之上做了封装,以增强易用性。

据了解,Hibernate3.2已经不再依赖cglib了,而直接依赖asm。

这些都不影响cglib的强大功能。

 

核心代码:

MyMethodInterceptor.java

package com.test.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class MyMethodInterceptor implements MethodInterceptor{

	@Override
	public Object intercept(Object object, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		  System.out.println(">>>MethodInterceptor start..."); 
		  Object result = methodProxy.invokeSuper(object,args); 
	      System.out.println(">>>MethodInterceptor ending..."); 
	      return result; 

	}

}

 测试:

package com.test.cglib;

import net.sf.cglib.proxy.Enhancer;

public class Test {
	public static void main(String rags[]){ 
        //Target target = new Target(); 
        Test test = new Test(); 
        Target proxyTarget = (Target)test.createProxy(Target.class); 
        String res=proxyTarget.execute(); 
        System.out.println("result:"+res); 
    } 

    public Object createProxy(Class targetClass){ 
        Enhancer enhancer = new Enhancer(); 
        enhancer.setSuperclass(targetClass); 
        enhancer.setCallback(new MyMethodInterceptor()); 
        return enhancer.create(); 
    } 

}
 

三,以一个实例在简单介绍下cglib的应用 ,我们模拟一个虚拟的场景,模拟对表的操作(代码参见附件dynamicProxyDemo.rar

1. 开始我们对表提供了CRUD方法,TableDAO.java

2. 创建一个DAO工厂,用来生成DAO实例,TableDAOFactory.java

3. 创建客户端,用来调用CRUD方法,Client.java

OK,完成了,CRUD方法完全被调用了。

当然这里并没有CGlib的任何内容。

问题不会这么简单的就结束,新的需求来临了

=====================================================================

Boss告诉我们这些方法不能开放给用户,只有“张三”才有权使用。

怎么办,难道我们要在每个方法上面进行判断吗

对了对了Proxy可能是最好的解决办法。jdk的代理就可以解决了。 好了我们来动手改造吧。等等jdk的代理需要实现接口

我们的dao类需要改变了。既然不想改动dao又要使用代理,我们这就请出CGlib

1. 只需新增一个权限验证的方法拦截器,AuthProxy.java

2. 对我们的dao工厂进行修改,我们提供一个使用代理的实例生成方法,getAuthInstance()

3. 客户端添加了两个方法用来验证不同用户的权限,haveAuth(),haveNoAuth()

OK,"张三"的正常执行,"李四"的没有执行。 

看到了吗?简单的aop就这样实现了

=====================================================================

 Boss又来训话了,不行不行,

 现在除了"张三"其他人都用不了了,现在不可以这样。他们都来向我反映了,必须使用开放查询功能

CGlib给我们提供了方法过滤器(CallbackFilter)

CallbackFilter可以明确表明,被代理的类中不同的方法, 被哪个拦截器所拦截

1. 下面我们就来做个过滤器用来过滤query方法,AuthProxyFilter.java

2. 在工场中新增一个使用了过滤器的实例生成方法,getAuthInstanceByFilter()

3. 客户端添加了个方法用来验证过滤器,haveAuthByFilter()

 

setCallbacks中定义了所使用的拦截器,

其中NoOp.INSTANCE是CGlib所提供的实际是一个没有任何操作的拦截器, 

他们是有序的。一定要和CallbackFilter里面的顺序一致。

上面return返回的就是返回的顺序。也就是说如果调用query方法就使用NoOp.INSTANCE进行拦截

 

 

ok,现在"李四"也可以使用query方法了,其他方法仍然没有权限。 

哈哈,当然这个代理的实现没有任何侵入性,无需强制让dao去实现接口

分享到:
评论

相关推荐

    浅谈JDK动态代理与CGLIB代理去区别

    本篇文章将深入探讨JDK动态代理和CGLIB代理的区别,以及它们在实际应用中的选择。 首先,JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类用于创建一个代理对象...

    Spring框架中JDK动态代理和cglib动态代理

    Spring 框架中 JDK 动态代理和 CGLIB 动态代理是 Spring AOP 中一个非常重要的知识点。Spring AOP 框架会根据实际情况选择使用 JDK 的动态代理还是 CGLIB 的动态代理。 JDK 动态代理是 Java 自带的动态代理机制,它...

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

    - **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成的子类,而JDK代理需要反射调用接口方法。 在实际开发中,如Spring AOP框架就同时支持JDK和...

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

    Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...

    JDK动态代理和Cglib动态代理实例源码

    - **灵活性**:JDK代理要求目标类实现接口,而Cglib无此限制。 - **使用场景**:如果目标类已经实现了接口,且不关心性能,优先选择JDK代理;否则,Cglib是更好的选择。 在`DynamicProxyTest`源码中,我们可以看到...

    JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)

    Java提供了两种主要的动态代理实现方式:JDK动态代理和CGLIB动态代理。 **JDK动态代理**: JDK动态代理基于接口实现,也就是说,被代理的对象必须实现至少一个接口。代理机制的核心是`java.lang.reflect.Proxy`类和...

    java代理机制 JDK动态代理和cglib代理 详解

    本文将深入探讨两种主要的Java代理实现:JDK动态代理和CGLIB代理。 一、JDK动态代理 JDK动态代理基于接口实现,它要求被代理的类必须实现至少一个接口。在运行时,Java会动态地创建一个新的类,这个类实现了与原始...

    JDK动态代理和CGLIB代理

    JDK动态代理和CGLIB代理是两种常用的实现方式。 首先,我们来看看JDK动态代理。JDK动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象...

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

    在Java中,代理模式有多种实现方式,包括静态代理、JDK动态代理和CGLIB动态代理。 **静态代理** 静态代理是最早也是最基础的代理实现方式。在静态代理中,我们需要创建一个代理类,这个代理类与原始类(被代理类)...

    jdk 的动态代理和CGLIB代理

    jdk 的动态代理和CGLIB代理

    Jdk动态代理,cglib动态代理,反射和拦截器(链)示例

    Java中的动态代理、反射和...总之,理解和掌握JDK动态代理、CGLIB动态代理、反射和拦截器是提升Java开发技能的关键步骤。通过实际操作这些示例,你将能够更好地应用这些技术到实际项目中,提高代码的灵活性和可维护性。

    java动态代理实例(jdk动态代理和cglib)

    以下是一个简单的CGLIB代理示例: ```java import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxyExample ...

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)

    本文主要介绍 Java 中两种常见的动态代理方式:JDK 原生动态代理和 CGLIB 动态代理。 一、 代理模式 代理模式是指程序通过代理类来访问目标对象,以达到对目标对象的控制和增强。代理模式的优点是可以在不改变目标...

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

    动态代理主要分为两种实现方式:JDK动态代理和CGLIB动态代理。 1. JDK动态代理: JDK动态代理基于Java的反射API,它要求被代理的目标对象必须实现一个或多个接口。JDK动态代理的核心类是`java.lang.reflect.Proxy`...

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

    Cglib 动态代理的实现方式是:我们首先需要定义一个类,然后使用 Cglib 库来生成该类的代理对象,该代理对象将拦截对被代理对象的所有方法调用,并控制对被代理对象的访问。 Cglib 动态代理的优点是:它的实现方式...

    JDK代理和Cglib代理

    JDK代理和Cglib代理是两种常用的动态代理实现方式。 **JDK代理(Java Dynamic Proxy)** JDK动态代理是Java标准库提供的一种代理机制,位于`java.lang.reflect`包下的`Proxy`类和`InvocationHandler`接口。JDK代理...

    输出JDK和CGLib动态代理产生的class文件.zip

    1. JDK代理项目: - src/main/java:包含目标接口和其实现类 - target/classes:编译后的class文件,包括目标接口和实现类的class文件,以及由Proxy生成的代理类class文件 - 测试代码:展示如何使用Proxy创建代理...

Global site tag (gtag.js) - Google Analytics