java 代理模式实现:java原生proxy类和增强型cglib库
2011-04-21 21:14
399 查看
大家可能都听说过spring的AOP编程,其实用java的反射机制也可以轻松实现。
我对AOP一个浅显的理解就是,当你在调用某个方法时,可以在调用之前或调用之后执行一些预前操作或预后操作,而不用更改被调用方法把预前操作或预后操作硬编码进去,你可以采用一种更灵活的方式,就是用代理模式来实现。
场景介绍:当我们在吃水果的时候,我们并不是直接拿到水果就吃,而是1.先用水洗洗水果,再2.吃水果,3.吃完后再洗洗手,擦擦嘴
操作2是我们直接想做的事,而操作1和操作3则是预前和预后操作。
怎么做呢?
用组合方法简单实现代理模式
实现1:
抽象一个Person接口,定义一个Person的实现类PersonA,再实现代理类
输出结果:
washing:apple
person A is eating:apple
washing hands
用java原生java.lang.reflect.Proxy实现
实现2只适应于特定接口的代理,如果我们想实现对任何接口的代理呢。
为什么现在只提到接口呢,可能你会问,为什么不直接对具体类进行代理呢?问的好,因为java.lang.reflect.Proxy类只能对接口进行代理,对具体类的代理要放到最后才讲,所以为了由浅入深,先卖个关子。君莫急。
实现2:
输出结果:
washing:apple
person A is eating:apple
washing hands
封装实现2
有人可能会觉得,我还得再写一个handler,再调用proxy.newInstance.好麻烦啊,能不能一次性搞定。好,给你。
虽然代理的是具体类,但需要具体类实现某个接口。但已经能模拟直接代理具体类了。
如这里虽然直接代理PersonA,但还是需要Person接口。等到了实现4就可以去掉Person接口了。
我还加了点东西,至于是什么,你看看就知道了。
实现3
washing:apple
person A is eating:apple
washing hands
-1 //看到这个就知道我加了什么了,我能对java.lang.Integer进行代理,但因为其实现的是Comparable<T>接口
//所以只能调用compareTo()方法
cglib实现
利器出现了,不需要你想代理的类实现莫个接口,是个类就行。所以在这里,可以去掉Person接口的定义了,不要再迷恋它了。很强大的吧
实现4
washing:apple
person A is eating:apple
washing hands
我对AOP一个浅显的理解就是,当你在调用某个方法时,可以在调用之前或调用之后执行一些预前操作或预后操作,而不用更改被调用方法把预前操作或预后操作硬编码进去,你可以采用一种更灵活的方式,就是用代理模式来实现。
场景介绍:当我们在吃水果的时候,我们并不是直接拿到水果就吃,而是1.先用水洗洗水果,再2.吃水果,3.吃完后再洗洗手,擦擦嘴
操作2是我们直接想做的事,而操作1和操作3则是预前和预后操作。
怎么做呢?
用组合方法简单实现代理模式
实现1:
抽象一个Person接口,定义一个Person的实现类PersonA,再实现代理类
public interface Person { public void eat(String fruit) ; } public class PersonA implements Person { public PersonA() { // TODO Auto-generated constructor stub } @Override public void eat(String fruit) { // TODO Auto-generated method stub System.out.println("person A is eating:"+fruit); } } public class PersonDelegate { public PersonDelegate(Person p) { // TODO Auto-generated constructor stub this.p = p ; } public Person p = null; public void eat(String fruit) { // TODO Auto-generated method stub washFruit(fruit); p.eat(fruit); clean(); } private void washFruit(String fruit){ System.out.println("washing:"+fruit); } private void clean(){ System.out.println("washing hands"); } public static void main(String[] args){ PersonDelegate delegate = new PersonDelegate(new PersonA()); delegate.eat("apple"); } }
输出结果:
washing:apple
person A is eating:apple
washing hands
用java原生java.lang.reflect.Proxy实现
实现2只适应于特定接口的代理,如果我们想实现对任何接口的代理呢。
为什么现在只提到接口呢,可能你会问,为什么不直接对具体类进行代理呢?问的好,因为java.lang.reflect.Proxy类只能对接口进行代理,对具体类的代理要放到最后才讲,所以为了由浅入深,先卖个关子。君莫急。
实现2:
public class PersonHandler implements InvocationHandler { public PersonA p = new PersonA(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Object rt = null; if(method.getName().equals("eat")){ washFruit((String)args[0]); rt = method.invoke(p, args); clean(); } return rt; } private void washFruit(String fruit){ System.out.println("washing:"+fruit); } private void clean(){ System.out.println("washing hands"); } public static void main(String[] args) { Person p = (Person) Proxy.newProxyInstance( Person.class.getClassLoader(), new Class[] { Person.class }, new PersonHandler()); p.eat("apple"); } }
输出结果:
washing:apple
person A is eating:apple
washing hands
封装实现2
有人可能会觉得,我还得再写一个handler,再调用proxy.newInstance.好麻烦啊,能不能一次性搞定。好,给你。
虽然代理的是具体类,但需要具体类实现某个接口。但已经能模拟直接代理具体类了。
如这里虽然直接代理PersonA,但还是需要Person接口。等到了实现4就可以去掉Person接口了。
我还加了点东西,至于是什么,你看看就知道了。
实现3
public class ProxyBroker implements InvocationHandler { private Object delegate = null; private ProxyBroker(Object delegate) { // TODO Auto-generated constructor stub this.delegate = delegate; } public static Object newProxy(Object obj) { ProxyBroker broker = new ProxyBroker(obj); Class[] interfaces = obj.getClass().getInterfaces(); Class inteface = null; if (Pattern .compile("^java[x]{0,1}") .matcher( obj.getClass() .getCanonicalName() .subSequence( 0, obj.getClass().getCanonicalName() .length())).find()) { if (obj.getClass().getInterfaces().length > 0) inteface = obj.getClass().getInterfaces()[0]; else System.err.println("no avaliable interface implemented by :" + obj.getClass().getCanonicalName()); } else { for (Class interfacc : interfaces) { if (!Pattern .compile("^java[x]{0,1}") .matcher( interfacc.getCanonicalName().subSequence(0, interfacc.getCanonicalName().length())) .find()) { inteface = interfacc; } } } return Proxy.newProxyInstance(inteface.getClassLoader(), new Class[] { inteface }, broker); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Object obj = null ; if(method.getName().equals("eat")){ washFruit((String)args[0]) ; obj = method.invoke(delegate, args); clean(); }else obj = method.invoke(delegate, args); return obj ; } public static void main(String[] args) { Person p = (Person) ProxyBroker.newProxy(new PersonA()); p.eat("apple"); Comparable intg = (Comparable) ProxyBroker.newProxy(new Integer(10)); System.out.println(intg.compareTo(11)); } private void washFruit(String fruit){ System.out.println("washing:"+fruit); } private void clean(){ System.out.println("washing hands"); } }
washing:apple
person A is eating:apple
washing hands
-1 //看到这个就知道我加了什么了,我能对java.lang.Integer进行代理,但因为其实现的是Comparable<T>接口
//所以只能调用compareTo()方法
cglib实现
利器出现了,不需要你想代理的类实现莫个接口,是个类就行。所以在这里,可以去掉Person接口的定义了,不要再迷恋它了。很强大的吧
实现4
public class CglibProxyBroker implements MethodInterceptor { private static CglibProxyBroker delegate = new CglibProxyBroker(); private CglibProxyBroker() { // TODO Auto-generated constructor stub } public static Object newInstance( Class clazz ){ try{ Enhancer e = new Enhancer(); e.setSuperclass(clazz); e.setCallback(delegate); return e.create(); }catch( Throwable e ){ e.printStackTrace(); throw new Error(e.getMessage()); } } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub Object obj = null; if(arg1.getName().equals("eat")){ washFruit((String)arg2[0]); obj = arg3.invokeSuper(arg0, arg2); clean(); }else obj = arg3.invokeSuper(arg0, arg2) ; return obj; } public static void main(String[] args) { Person p = (Person)CglibProxyBroker.newInstance(new PersonA().getClass()); p.eat("apple"); } private void washFruit(String fruit){ System.out.println("washing:"+fruit); } private void clean(){ System.out.println("washing hands"); } }
washing:apple
person A is eating:apple
washing hands
相关文章推荐
- 详解使用Java原生代理实现AOP实例
- (Proxy)代理模式的Java实现
- Java设计模式之代理模式2-动态代理(jdk实现)
- 使用Java原生代理实现注入
- Java中代理模式的实现步骤
- 详解设计模式中的proxy代理模式及在Java程序中的实现
- 代理模式之Java动态代理实现方法
- (java)简单实现原生RabbitMQ中的广播订阅(fanout)模式
- 大话设计模式4 代理模式 的java代码实现
- 代理模式[java实现]
- 使用Java原生代理实现AOP
- Java动态代理模式jdk和cglib的2种实现以及二者的区别(AOP面向切面的前奏)
- 大白话讲解设计模式之:代理模式 Java语言实现
- 使用Java原生代理实现数据注入
- (Dynamic Proxy)动态代理模式的Java实现
- java 代理模式,JDK动态代理,SpringAOP的实现
- Java基础之反射及动态代理,反射实现工厂模式
- Java开发-Java中代理设计模式的实现
- JAVA 代理模式之通用接口/继承的实现方式
- java反射机制(三)---java的反射和代理实现IOC模式 模拟spring