大家可能都听说过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
- public class ProxyBroker implements InvocationHandler {
- private Object delegate = null;
- private ProxyBroker(Object delegate) {
-
- 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 {
-
- 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() {
-
- }
- 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 {
-
- 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
|