Spring温故知新(六)AOP面向切面编程 <2>
上一章我们讲到了用代理模式来实现自动管理ISpeaker接口里的say()方法,自动的在say()方法前后加上我们get/give礼物的方法。
但是想法比较全面的同学可能也会想到,如果不仅仅只有ISpeaker里的say()方法需要自动送礼物,如果还有这个接口里的其他方法、甚至于是其他接口的方法也需要实现自动送礼物,那又该怎么办呢?
如果还是安装之前的代理模式来做的话那就得每个接口都写一个几乎相同的送礼物的代理类,区别仅在于代理类的接口不同。这样的话耦合性还是太高了,那么还有什么更好的办法吗?
一切皆有可能嘛~ JAVA标准库里面就有一种利用反射的可以实现不依赖接口的动态代理方法,那就是实现java.lang.reflect.InvocationHandler接口。下面我们来看一下怎么样用InvocationHandler接口来实现动态代理:
新的自动送礼物代理器:
package com.iteye.bolide74.action;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class GiftDynamicProxy implements InvocationHandler {Object target;public Object bind(Object target) {//截取了被绑定的、需要被代理的实例对象,交给类成员targetthis.target = target;//返回一个新的"代理实例",也就是说外部调用了bind方法以后,获取到的就不是传进来的那个实例对象了,而是被"封装"过的代理实例return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object result = null;//获取礼物getGift();//拦截了真正的目标实例对象的方法以后,利用反射来自动调用相同方法//this.target就是被代理的实例对象//这里的args数组就是方法调用时传递的实参数组result = method.invoke(this.target, args);//方法调用完毕以后再赠予礼物giveGift();return result;}public void getGift() {System.out.println("获取了一个礼物");}public void giveGift() {System.out.println("赠予一个礼物");}}package com.iteye.bolide74.impl;public interface IVisit {public void sayByVisit();}package com.iteye.bolide74.action;import com.iteye.bolide74.impl.IVisit;public class People implements IVisit {public String name;public People(String name) {this.name = name;}@Overridepublic void sayByVisit() {System.out.println(this.name + "正在访问邻居家,在那坐了一会");}}package com.iteye.bolide74.tester;import com.iteye.bolide74.action.GiftDynamicProxy;import com.iteye.bolide74.action.People;import com.iteye.bolide74.action.Robot;import com.iteye.bolide74.impl.ISpeaker;import com.iteye.bolide74.impl.IVisit;public class GiftDynamicProxyTester {public static void main(String[] args) {GiftDynamicProxy giftDP = new GiftDynamicProxy();ISpeaker wallE = (ISpeaker) giftDP.bind(new Robot("Wall-E"));wallE.say("你好");System.out.println();//调用同一个Gift动态代理实例,无需重写IVisit girlFriend = (IVisit) giftDP.bind(new People("GirlFriend"));girlFriend.sayByVisit();}}