java 代理的三种实现方式
Java 代理模式有如下几种实现方式:
1.静态代理。
2.JDK动态代理。
3.CGLIB动态代理。
示例,有一个打招呼的接口。分别有两个实现,说hello,和握手。代码如下。
接口:
public interface Greeting {
public void doGreet();
}
实现类:
public class SayHello implements Greeting {
@Override
public void doGreet() {
System.out.println("Greeting by say 'hello' .");
}
}
public class ShakeHands implements Greeting {
@Override
public void doGreet() {
System.out.println("Greeting by shake others's hands .");
}
}
public class KissHello {
public void doGreet() {
System.out.println("Greeting by kiss . ");
}
}
在不改变代码的情况下,想在执行目标方法 前后 做一些其他操作。则可以通过代理方式来实现。
1.静态代理。需要创建代理类。代理类实现了和目标类一样的接口,代理类接收目标类对象,并在实现方法中调用目标类的实现方法前后做手脚。如下:
public class GreetStaticProxy implements Greeting {
private Greeting hello;//被代理对象
public GreetStaticProxy(Greeting hello){
this.hello=hello;
}
@Override
public void doGreet() {
before();//执行其他操作
this.hello.doGreet();//调用目标方法
after();//执行其他操作
}
public void before(){
System.out.println("[StaticProxy] Come to someone.");
}
public void after(){
System.out.println("[StaticProxy] Back to his own corner");
}
}
测试调用:
public class Main {
public static void main(String[] args) {
Greeting hello=new SayHello();
Greeting shakeHands=new ShakeHands();
//静态代理
GreetStaticProxy staticHelloProxy=new GreetStaticProxy(hello);
staticHelloProxy.doGreet();
System.out.println();
GreetStaticProxy shakeHandsProxy=new GreetStaticProxy(shakeHands);
shakeHandsProxy.doGreet();
}
运行结果:
[StaticProxy] Come to someone.
Greeting by say 'hello' .
[StaticProxy] Back to his own corner [StaticProxy] Come to someone.
Greeting by shake others's hands .
[StaticProxy] Back to his own corner
这个方式有弊端,如果有N个接口的实现类需要被代理,则需要创建N个代理类。
2.JDK动态代理
创建代理类,如下:
public class JdkProxy implements InvocationHandler {
private Object target;
public JdkProxy(Object obj){
this.target=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
before();
result=method.invoke(target, args);
after();
return result;
}
public void before(){
System.out.println("[JdkProxy] Come to someone.");
}
public void after(){
System.out.println("[JdkProxy] Back to his own corner");
}
}
测试调用:
public class Main {
public static void main(String[] args) {
Greeting hello=new SayHello();
Greeting shakeHands=new ShakeHands();
//jdk动态代理
JdkProxy dynamicProxy=new JdkProxy(hello);
Greeting target=(Greeting) Proxy.newProxyInstance(hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(), dynamicProxy);
target.doGreet();
System.out.println();
}
}
这种方式和第一种方式相比,虽然不需要创建很多代理类,
但是,他依赖与“被代理的对象需要实现接口” 即:在上面给出的代码示例中,动态代理可以代理SayHello和ShakeHands,却不能代理KissHello。因为KissHello没有实现接口。
3.CGLIB动态代理。
创建代理类:
public class CglibProxy implements MethodInterceptor {
public static CglibProxy proxy=new CglibProxy();
private CglibProxy(){}
public static CglibProxy getInstance(){
return proxy;
}
public <T> T getProxy(Class<T> cls){
return (T) Enhancer.create(cls, this);
}
@Override
public Object intercept(Object obj, Method method, Object[] arg,
MethodProxy proxy) throws Throwable {
Object result=null;
try {
before();
result= proxy.invokeSuper(obj, arg);
after();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public void before(){
System.out.println("[cglib] Come to someone.");
}
public void after(){
System.out.println("[cglib] Back to his own corner.");
}
}
调用示例:
public class Main {
public static void main(String[] args) {
//cglib代理
Greeting targetProxy=CglibProxy.getInstance().getProxy(SayHello.class);
targetProxy.doGreet();
System.out.println();
CglibProxy.getInstance().getInstance().getProxy(KissHello.class).doGreet();
}
}
综上,CGLIB动态代理最好,spring框架也用到了CGLIB包。
java 代理的三种实现方式的更多相关文章
- Java多线程的三种实现方式
java多线程的三种实现方式 一.继承Thread类 二.实现Runnable接口 三.使用ExecutorService, Callable, Future 无论是通过继承Thread类还是实现Ru ...
- java的list几种实现方式的效率(ArrayList、LinkedList、Vector、Stack),以及 java时间戳的三种获取方式比较
一.list简介 List列表类,顺序存储任何对象(顺序不变),可重复. List是继承于Collection的接口,不能实例化.实例化可以用: ArrayList(实现动态数组),查询快(随意访问或 ...
- Java定时器的三种实现方式
一.普通thread /** * 普通thread * 这是最常见的,创建一个thread,然后让它在while循环里一直运行着, * 通过sleep方法来达到定时任务的效果.这样可以快速简单的实现, ...
- Java数组的三种打印方式
1.数组的输出的三种方式 一维数组: 定义一个数组 int[] array = {1,2,3,4,5}; (1)传统的for循环方式 for(int i=0;i<array.length;i++ ...
- Java反射的三种实现方式
Foo foo = new Foo(); 第一种:通过Object类的getClass方法 Class cla = foo.getClass(); 第二种:通过对象实例方法获取对象 Class cla ...
- java 多线程编程三种实现方式
一种是继承Thread类,一种是实现Runable接口,还有一种是实现callable接口: 有博主说只有前面2种方式,我个人愚见是三种,主要详细介绍下callable的使用: 三种线程的我的个人理解 ...
- java集合的三种遍历方式
import java.util.ArrayList; import java.util.Collection;import java.util.Iterator;public class Home ...
- java线程的三种实现方式
线程实现的三种种方式: 一个是继承Thread类,实现run()方法: 一个是实现Runnable接口,实现run()方法: 一个是实现Callable接口,实现call()方法:该方式和实现Runn ...
- Java规范的三种注释方式:
1.单行注释 // //单行注释 2.多行注释 /* */ /* 多行 注释 */ 3.文档注释[java特有的] /** */ ◆注释内容可以被JDK提供的工具javadoc所解析,生成一套以网页文 ...
随机推荐
- C#窗体 流
流:(I/O)输入输出流 分类:文件流,内存流,网络流 流的操作一般要放在try catch里面,操作文件网络容易出现异常 命名空间:using system .IO;using system .Te ...
- java mybatis 中sql 模糊查询
示例: like concat('%',#{groupName},'%') //-------------- <select id="findList" resultType ...
- Normalize.css 与 reset.css
Normalize.css 与 reset.css都是初始化页面样式 不同点在于 reset.css更加粗暴,直接把所有的样式全部初始化了: Normalize.css还剩点良心,还保留了一些浏览器默 ...
- Java多线程编程——进阶篇一
一.线程栈模型与线程的变量 要理解线程调度的原理,以及线程执行过程,必须理解线程栈模型. 线程栈是指某一时刻内存中线程调度的栈信息,当前调用的方法总是位于栈顶.线程栈的内容是随着程序的运行动态变化的, ...
- 设置irb和ri
设置irb和ri 输入ruby -v查看是否能够显示ruby版本 现在可以 配置irb了. irb是交互式Ruby 的命令行工具,即输入一句就立即执行并给出结果. 默认的irb不够强大,现在给它配置一 ...
- Android之使用Volley框架在ListView中加载大量图片
1.listview 中的条目要用 Volley 中的 NetworkImageView,如果直接用ImageView也可以,但是要在getView方法中使用url地址设置为imageView的tag ...
- Deferred解决JS同步问题
测试脚本: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- 初识Python第三天(二)
2.2 OrderedDict有序字典 import collections dic = collections.OrderedDict() dic['k1'] = 'v1' dic['k2'] = ...
- img的hover事件闪动
今天给同学写一个相册照片鼠标浮动显示细节的效果,遇到了闪动的bug,也顺利解决,就写下来跟大家分享. 我使用的是'标签:hover + 标签'的形式,如果使用jquery的mouseover.mous ...
- python异常和错误(syntax errors 和 exceptions)
语法错误 语法错误又被称解析错误 >>> for i in range(1..10):print(i) File "<stdin>", line 1 ...