JAVA代理方式使用示例总结

JAVA代理方式使用示例总结

一、    代理方式概括

  Java的代理方式主要包含了静态代理,动态代理两种方式,其中,动态代理根据实现的方式不同,又可以划分为jdk动态代理和cglib动态代理.

二、    代理方式实现

1.    静态代理

  静态代理,主要包含两个实例,被代理类和代理类,两者都要实现公共的接口,能够面向接口实现,把被代理类组合到代理类中,在被代理类的本身功能上,加上代理类的自己的处理逻辑,达到增强的效果,就简单的实现了代理功能.静态代理只能事先编写好代理代码,经过统一编译后才能执行.下面简单的代码实现:

1.1建立公共的接口

package jdkcglib.dynmicagent;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public interface IBookFacade {

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    void addBook(String name);

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    void deleteBook();

}

1.2建立被代理类


package jdkcglib.dynmicagent;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class BookFacade implements IBookFacade {

    @Override
    public void addBook(String name) {
        System.out.println("增加图书!"+name);
    }

    @Override
    public void deleteBook() {
        System.out.println("删除图书!");
    }
}

1.3建立代理类

package com.lilin.maven.service;

/**
 * @author lilin
 * 
 */
public class BookFacadeProxy implements IBookFacade {
    private BookFacade bookFacade;

    public BookFacadeProxy(BookFacade bookFacade) {
        this.bookFacade = bookFacade;
    }

    @Override
    public void addBook(String name) {
        System.out.println("新增之前。。。");
        bookFacade.addBook("红楼梦");
        System.out.println("新增之后。。。");
    }

    @Override
    public void deleteBook() {
        System.out.println("删除之前。。。");
        bookFacade.deleteBook();
        System.out.println("删除之后。。。");
    }

}

 

1.4建立测试类

package jdkcglib.dynmicagent;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class Test {

    /**
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param args
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */

    public static void main(String[] args) {
      BookFacadeProxy proxy = new BookFacadeProxy(new BookFacade());
      proxy.addBook("红楼梦");
      proxy.deleteBook();
    }

}

2.    动态代理---jdk动态代理(InvocationHandler 接口)

  依据java的反射机制动态生成.在运行期间可以动态生成被代理类的实例.利用反射。获取托付类的类载入器。托付类的全部接口,实例化代理类。通过反射类Proxy以及InvationHandler回调接口实现的。可是动态代理类仅仅能对该类所实现的接口中的方法进行代理。具有一定的局限性,而且反射的效率也不是非常高。下面是简单的代码实现:

2.1 建立公共接口类

package jdkcglib.dynmicagent;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public interface IBookFacade {

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    void addBook(String name);

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    void deleteBook();

}

2.2 建立被代理类

package jdkcglib.dynmicagent;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class BookFacade implements IBookFacade {

    @Override
    public void addBook(String name) {
        System.out.println("新增加图书!"+name);
    }

    @Override
    public void deleteBook() {
        System.out.println("直接删除图书!");
    }

}

2.3 建立代理类

package jdkcglib.dynmicagent;

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

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 * 
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class BookFacadeProxy implements InvocationHandler {

    /**
     * 被代理对象
     */
    private Object target;

    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉绑定被代理对象 返回代理对象
     * 
     * @param target
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public Object bind(Object target) {
        this.target = target;
        // 要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
        // 返回代理对象
        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;
        if (method.getName().startsWith("delete")) {
            System.out.println("#####方法执行之前#####");
            result = method.invoke(target, args);
            System.out.println("#####方法执行之后#####");
        } else {
            result = method.invoke(target, args);
        }
        return result;
    }

}

2.4 建立测试类

package jdkcglib.dynmicagent;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class Test {

    /**
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param args
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void main(String[] args) {
        BookFacadeProxy proxy = new BookFacadeProxy();
        IBookFacade bookProxy = (IBookFacade) proxy.bind(new BookFacade());
        bookProxy.addBook("红楼梦");
        bookProxy.deleteBook();
    }
}

3.    动态代理---CGLIB动态代理(MethodInterceptor 接口)

  CGLib (Code Generation Library) 是一个强大的,高性能,高质量的Code生成类库。它能够在执行期扩展Java类与实现Java接口。不仅仅能够接管接口类的方法,同时还能够接管普通类的方法.解决了jdk代理的只能代理接口类方法的难处,CGLib 的底层是Java字节码操作框架(ASM).动态的生成被代理类的子类, 增强的代码是硬编码在新生成的类文件内部的,不会存在反射的性能问题.下面是简单的代码实现:

3.1 建立被代理类

package jdkcglib.cglib;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class BookFacade {

    public void addBook() {
        System.out.println("增加图书的普通方法...");
    }

}

3.2 建立代理类

package jdkcglib.cglib;

import java.lang.reflect.Method;

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

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class BookFacadeCglib implements MethodInterceptor {

    private Object target;

    /**
     * 创建代理对象
     * 
     * @param target
     * @return
     */
    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        // 回调方法
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("方法执行之前");
        proxy.invokeSuper(obj, args);
        System.out.println("方法执行之后");
        return null;
    }

}

3.3  建立测试类

package jdkcglib.cglib;

import java.io.UnsupportedEncodingException;

/**
 * 
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 * 
 * @author 12061799
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class TestCglib {
    /**
     * 
     * 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param args
     * @throws UnsupportedEncodingException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static void main(String[] args) throws UnsupportedEncodingException {
        BookFacadeCglib cglib = new BookFacadeCglib();
        BookFacade bookCglib = (BookFacade) cglib.getInstance(new BookFacade());
        bookCglib.addBook();
    }

}

三、  java代理小结

静态代理: 代理类就是通过调用被代理类的方法进行执行的,自己本身并不用清楚被代理类的方法.需要编译后执行.耦合比较紧密.

JDK动态代理: 利用反射原理,动态的生成代理类,将类的载入延迟到程序执行之中,解耦了代理类和被代理类的联系.主要要实现InvationHandler接口.

CGLIB动态代理:原理是继承,把被代理类作为父类,动态生成被代理类的子类,三个步骤,设置父类,设置回调函数,创建子类.实现MethodInterceptor 接口,拦截调用父类方法时,会处理回调方法,处理自己的增强方法.

参考:

http://www.cnblogs.com/bhlsheji/p/5316693.html

 

posted @ 2016-03-26 16:45  青天流云  阅读(3150)  评论(3编辑  收藏  举报