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 接口,拦截调用父类方法时,会处理回调方法,处理自己的增强方法.
参考: