zoukankan      html  css  js  c++  java
  • java动态代理和cglib动态代理

    动态代理应用广泛,Spring,Struts等框架很多功能是通过动态代理,或者进一步封装来实现的。

    常见的动态代理模式实现有Java API提供的动态代理和第三方开源类库CGLIB动态代理。

    Java API提供的动态代理是基于类反射实现的,用到的类有:

    java.lang.reflect.InvocationHandler;

    java.lang.reflect.Method;

    java.lang.reflect.Proxy;

    其实现是通过Proxy类的newProxyInstance()方法产生代理对象。自定义动态代理类需要实现InvocationHandler接口,该接口只有一个invoke()方法。


    CGLIB是通过生成java 字节码从而动态的产生代理对象,因此需要字节码解析处理的依赖asm类库,字节码动态生成的代理对象实际上是继承了真实主题类的。这种实现方式需要导入cglib和asm的类库。下面用到的例子是cglib-2.2.2.jar, asm-3.3.1.jar。cglib使用了MethodInterceptor,其中的方法是intercept(),这是拦截的概念,很容易就想到了Struts2的拦截器。

    比较之下,Java API提供的动态代理需要面向接口,产生代理对象,因此真实主题实现类必须实现了接口才可以。而CGLIB不需要面向接口,可以代理简单类,但由于动态代理对象是继承真实主题实现类的,因此要求真实主题实现类不能是final的。

    下面是实现的例子。

    首先,为了看到动态代理可以根据不同类动态产生不同代理的效果,我们新建两个接口,及其实现类。

    package leon.aj.dynproxy.target;
    
    public interface Hello {
    	public String sayHello(String name);
    }
    

    实现类:

    package leon.aj.dynproxy.target;
    
    public class HelloImpl implements Hello {
    	@Override
    	public String sayHello(String name) {
    		String s = "Hello, "+name;
    		System.out.println(this.getClass().getName()+"->"+s);
    		return s;
    	}
    }

    另一接口和实现类:

    package leon.aj.dynproxy.target;
    
    public interface UserDao {
    	public boolean login(String username,String password);
    }
    package leon.aj.dynproxy.target;
    
    public class UserDaoImpl implements UserDao {
    	@Override
    	public boolean login(String username, String password) {
    		String user = "("+username+","+password+")";
    		System.out.println(this.getClass().getName()+"-> processing login:"+user);
    		return true;
    	}
    }


    应用Java API实现的动态代理类:

    package leon.aj.dynproxy.java;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class JavaDynProxy implements InvocationHandler{
    	private Object target;
    	public Object getProxyInstance(Object target){
    		this.target = target;
    		return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
    				target.getClass().getInterfaces(), this);
    	}
    	
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)
    			throws Throwable {
    		Object result = null;
    		System.out.println("before target method...");
    		result = method.invoke(target, args);
    		System.out.println("after target method...");
    		return result;
    	}
    }

    测试:

    package leon.aj.dynproxy.java;
    
    import leon.aj.dynproxy.target.Hello;
    import leon.aj.dynproxy.target.HelloImpl;
    import leon.aj.dynproxy.target.UserDao;
    import leon.aj.dynproxy.target.UserDaoImpl;
    
    public class TestJavaProxy {
    	public static void main(String[] args) {
    		JavaDynProxy proxy = new JavaDynProxy();
    		Hello hello = (Hello)proxy.getProxyInstance(new HelloImpl());
    		String s = hello.sayHello("Leon");
    		System.out.println(s);
    		
    		UserDao userDao = (UserDao) proxy.getProxyInstance(new UserDaoImpl());
    		userDao.login("Leon", "1234");
    		System.out.println(userDao.getClass().getName());
    	}
    }


    下面是采用cglib实现的例子:

    package leon.aj.dynproxy.cglib;
    
    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class CglibProxy implements MethodInterceptor {
    	private Object target;  
    	
        public Object getProxyInstance(Object target) {  
        	this.target = target;
            Enhancer enhancer = new Enhancer();  
            enhancer.setSuperclass(this.target.getClass());  
            enhancer.setCallback(this);  // call back method
            return enhancer.create();  // create proxy instance
        }  
    	
    	@Override
    	public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    		System.out.println("before target method...");
    		Object result = proxy.invokeSuper(target, args);
    		System.out.println("after target method...");
    		return result;
    	}
    }

    测试类:

    package leon.aj.dynproxy.cglib;
    
    import leon.aj.dynproxy.target.Hello;
    import leon.aj.dynproxy.target.HelloImpl;
    import leon.aj.dynproxy.target.UserDaoImpl;
    
    public class TestCiglib {
    	public static void main(String[] args) {
    		CglibProxy proxy = new CglibProxy();
    		Hello hello = (Hello) proxy.getProxyInstance(new HelloImpl());
    		System.out.println(hello.sayHello("Leon"));
    		UserDaoImpl userDao = (UserDaoImpl) proxy.getProxyInstance(new UserDaoImpl());
    		userDao.login("Leon", "1234");
    		System.out.println(userDao.getClass().getSuperclass());//看动态代理实例的父类
    	}
    }












  • 相关阅读:
    docker 命令
    php cli命令
    windows 中docker连接使用mysql数据库
    什么是微服务
    PHP7新特性
    Docker Machine 命令
    关于Docker目录挂载的总结(二)
    实验十一 MySQLl备份与恢复1
    实验十--- MySQL过程式数据库对象
    实验九 存储函数和触发器
  • 原文地址:https://www.cnblogs.com/riskyer/p/3220292.html
Copyright © 2011-2022 走看看