简介 Spring AOP实现原理是java语言的动态代理,学习后写篇日记记录下来!
原理 java动态代理的原理为:使用java反射生成与委托类相同接口的代理类,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
Java反射 java反射主要涉及的是java.lang.Class、java.lang.reflect.Constructor、java.lang.reflect.Field、java.lang.reflect.Method等类。下面的demo来演示反射的一些基本使用方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package com.demo.proxy; * Created by 程祥 on 15/12/30. * Function:学习反射用的model */ public class ReflectModel { private String string; public int num; private String [] arr; public void voidMethod(String arg){ System.out.println ("voidMethod********" +arg); } public String argMethod(String arg){ System.out.println (arg); return arg+"******argMethod" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package com.demo.proxy; import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Arrays; * Created by 程祥 on 15/12/30. * Function:反射学习测试 */ public class ReflectTest { public static void main(String [] args){ try { Class reflectClass = Class.forName("com.demo.proxy.ReflectModel" ); ReflectModel reflectObj = (ReflectModel)reflectClass.newInstance(); reflectObj.voidMethod("reflectObj" ); Constructor constructor = reflectClass.getConstructor(); ReflectModel constructorObj = (ReflectModel)constructor .newInstance(); //可以正常输出 reflectObj.voidMethod("constructorObj"); Method voidMethod = reflectClass.getMethod("voidMethod",String .class ); voidMethod.invoke(constructorObj, "methodInvoke"); Method arrMthod = reflectClass.getMethod("setArr",String [].class ); String [] arrStr = {"aaa" ,"bb" }; arrMthod.invoke(constructorObj, (Object ) arrStr); System.out.println(Arrays.toString(constructorObj.getArr())); Method setNum = reflectClass.getMethod("setNum",int.class ); setNum.invoke(constructorObj,100); //都需要考虑访问性 private /protect/public Field numField = reflectClass.getField("num"); System.out.println(numField.getInt(constructorObj)); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } }
Java动态代理 动态代理使用java反射生成与委托类相同接口的代理类,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。原理如上图,demo如下:
1 2 3 4 5 package com.demo.proxy;public interface TestService { void printText () ; }
1 2 3 4 5 6 7 8 9 package com.demo.proxy.impl;import com.demo.proxy.TestService;public class TestServiceImpl implements TestService { public void printText () { System.out.println("*****TestServiceImpl******" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.demo.proxy.impl; import java.lang.reflect.InvocationHandler ;import java.lang.reflect.Method ;import java.lang.reflect.Proxy ;public class ProxySubject implements InvocationHandler { //被代理对象 private Object object ; public ProxySubject (Object object ) { this.object = object ; } public Object getProxyBean(){ //返回代理对象 return Proxy .newProxyInstance(object .getClass().getClassLoader(), object .getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method , Object [] args) throws Throwable { //代理增强 System .out .println("InvokeImpl proxy add function~" ); //使用反射 Object result = method .invoke(object , args); System .out .println(proxy.getClass().getName()); //。。。some other function return result ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.demo.proxy; import com.demo.proxy.impl.ProxySubject; import com.demo.proxy.impl.TestServiceImpl; import java.lang.reflect.Proxy; public class Client { public static void main( String[ ] args) { TestService service = new TestServiceImpl() ; ProxySubject invoke = new ProxySubject(service) ; TestService proxy = ( TestService) invoke.getProxyBean() ; //实现功能与正常实现类一样,并添加了相应增强功能 proxy.printText( ) ; } }
结语 java反射功能非常强大,用处特别多。动态代理和CGLIB的区别是动态代理使用于接口模式下,CGLIB使用于类与类之间的继承,CGLIB新生成了一个继承自原类的子类,CGLIB不适用与被final修饰的类进行代理。