spring原始碼AOP解析
阿新 • • 發佈:2018-11-16
1、代理技術(靜態代理、JDK動態代理、CGLib代理)
靜態代理: |-- Hello |-- void say(String name); |-- HelloImpl implements Hello { voiv say(String name){ sysout("Hello!"+name); } } |-- HelloProxy implents Hello { Hello hello; HelloProxy(){ hello = new HelloImpl(); } voiv say(String name){ before(); sysout(View Code"Hello!"+name); end(); } void before(){ sysout("Before"); } void after(){ sysout("After"); } main(String[] args){ Hello hello = new HelloProxy(); hello.say("Jack"); } } JDK動態代理: |-- DynamicProxy implements InvocationHandler { Object target; DynamicProxy (Object target){this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args){ before(); object result = method.invoke(target, args); after(); return result; } ... main(String[] args){ // 嘗試1 Hello hello = newHelloImpl(); DynamicProxy dynamicProxy = new DynamicProxy(hello); Hello hello = (Hello)Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass.getInterfaces(), dynamicProxy); hello.say("Jack"); // 嘗試2 DynamicProxy dynamicProxy = new DynamicProxy(new HelloImpl()); Hello hello = dynamicProxy.getProxy(); hello.say("Jack"); } public <T> T getProxy(){ return (T)Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass.getInterfaces(), this ); } } CGLib動態代理: |-- CGLibProxy implements MethodInterceptor { private static CGLibProxy instance = new CGLibProxy(); private CGLibProxy() {} public CGLibProxy getInstance(){ return instance; } public <T> T getProxy(Class<T> cls){ return (T) Enhancer.create(cls, this); } public Object inercept(Object obj, Method method, Object[] args, MethodProxy proxy){ before(); Object result = proxy.invokeSuper(obj, args); after(); return result; } ... main(String[] args){ // 嘗試1 CGLibProxy cgLibProxy = new CGLibProxy(); Hello helloProxy = cgLibProxy.getProxy(HelloImpl.class); helloProxy.say("Jack"); // 嘗試2 Hello helloProxy =CGLibProxy.getInstance().getProxy(HelloImpl.class); helloProxy.say("Jack"); } }
2、AOP技術
|-- interface Greeting |-- void sayHello(String name); |-- GreetingImpl implements Greeting |-- sayHello(String name){ before(); sysout("Hello!"+name); after(); } |-- GreetingProxy implements Greeting |-- GreetingImpl greetingImpl; |-- GreetingProxy(GreetingImpl greetingImpl) -> this.greetingImpl = greetingImpl; |-- sayHello(String name){ before(); greetingImpl.sayHello(); after(); } |-- before() -> sysout("Before"); |-- after() -> sysout("After"); |-- main(String[] args){ Greeting greetingProxy = new GreetingProxy(new GreetingImpl()); greetingProxy.sayHello("Jack"); } |-- JDKDynamicProxy implements InvocationHandler { Object target; JDKDynamicProxy (Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args){ before(); object result = method.invoke(target, args); after(); return result; } public <T> T getProxy(){ return (T)Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass.getInterfaces(), this ); } private void before(){ sysout("Before"); } private void after(){ sysout("After"); } main(String[] args){ Greeting greeting = new JDKDynamicProxy(new GreetingImpl()).getProxy(); greeting.sayHello("Jack"); } } |-- CGLibProxy implements MethodInterceptor{ private static CGLibProxy instance = new CGLibProxy(); private CGLibProxy() {} public CGLibProxy getInstance(){ return instance; } public <T> T getProxy(Class<T> cls){ return (T) Enhancer.create(cls, this); } public Object inercept(Object obj, Method method, Object[] args, MethodProxy proxy){ before(); Object result = proxy.invokeSuper(obj, args); after(); return result; } main(String[] args){ Greeting greeting = CGLibProxy.getInstance().getProxy(GreetingImpl.class); greeting.sayHello("Jack"); } }View Code
3、spring AOP技術
|-- GreetingBeforeAdvice implements MethodBeforeAdvice |-- before(Method method, Object[] args, Object target) throws Throwable -> sysout("Before"); |-- AfterReturningAdvice |-- afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable -> sysout("after"); |-- GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice |-- before(Method method, Object[] args, Object target) throws Throwable -> sysout("Before"); |-- afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable -> sysout("after"); |-- GreetingAroundAdvice implements MethodInterceptor // 環繞增強(org.aopalliance.intercept.MethodInterceptor,AOP聯盟) |-- Object invoke(MethodInvocation invocation){ before(); Object result = invocation.proceed(); after(); } |-- before() -> sysout("Before") |-- after() -> sysout("After") |-- main (String[] args){ ProxyFactory proxyFactory = new ProxyFactory(); // 建立代理工廠 proxyFactory.setTarget(new GreetingImpl()); // 射入目標類物件 // proxyFactory.addAdvice(new GreetingBeforeAdvice()); // 新增前置增強 // proxyFactory.addAdvice(new AfterReturningAdvice()); // 新增後置增強 // proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice()); // 新增前後置增強 proxyFactory.addAdvice(new GreetingAroundAdvice()); // 新增環繞增強 Greeting greeting = (Greeting)proxyFactory.getProxy(); // 從代理工廠獲取代理物件 greeting.sayHello("Jack"); // 呼叫代理方法 } |-- 配置檔案-spring.xml <!-- 掃描指定包(將帶有@componet註解類自動定義為Spring bean) --> <context:componet-scan base-package="aop.demo"/> <!-- 配置一個代理 --> <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="aop.Greeting"></property><!-- 需要代理的介面 --> <property name="target" value="greetingImpl"></property><!-- 介面實現類 --> <!-- <property name="target" value="greetingAroundAdvice"></property> --> <property name="interceptorNames"> <list> <value>greetingAroundAdvice</value> </list> </property> </bean> spring2.5+特性,@Component @Component public calss GreetingImpl implements Greeting { ... } --> <bean id="xxx" class="xxx"> |-- 客戶端呼叫 |-- main(String[] args){ ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml"); Greeting greeting = (Greeting)context.getBean("greetingProxy"); greeting.sayHello("Jack"); } |-- 丟擲增強-ThrowsAdvice |-- GreetingThrowAdvice implements ThrowsAdvice { public void afterThrowing(Method method, Object[] args, Object target, Exception e){ sysout("--------- Throw Exception ---------"); sysout("Target Class: " + target.getClass().getName()); sysout("Method Name: " + method.getName()); sysout("Exception Message: " + e.getMessage()); sysout("-----------------------------------"); } } |-- 引入增強 |-- interface Apology |-- void saySorry(String name); |-- @Component GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology { @Override public Object invoke(MethodInvocation invocation) throws Throwable{ return super.invoke(invocation); } @Overrice public void saySorry(String name){ sysout("Sorry! + name); } } |-- 配置檔案-spring.xml <!-- 掃描指定包(將帶有@componet註解類自動定義為Spring bean) --> <context:componet-scan base-package="aop.demo"/> <!-- 配置一個代理 --> <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="aop.demo.Apology"></property><!-- 需要動態實現的介面 --> <property name="target" value="greetingImpl"></property><!-- 目標類 --> <property name="interceptorNames" value="greetingIntroAdvice"></property> <!-- 引入增強 --> <property name="proxyTargetClass" value="true"/> <!-- 代理目標類(預設為false,代理介面)--> </bean> |-- 呼叫 |-- main(String[] args){ ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml"); GeetingImpl greetingImpl = (GeetingImpl)context.getBean("greetingProxy"); // 轉型為目標類,而非它的介面 greetingImpl.sayHello("Jack"); Apology apology = (Apology) greetingImpl; // 將目標型別強制向上轉型為Apology介面(這就是引入增強給我們帶來的特性,也就是“介面動態實現”功能) apology.saySorry("Jack"); } |-- AOP 切面 |-- @Component public class GreetingImpl implements Greeting { @Override public void sayHello(){ sysout("Hello!" + name); } public void goodMorning(String name){ sysout("Good Morning!" + name); } public void goodNight(String name){ sysout("Good Night!" + name); } } |-- 配置檔案-spring.xml <!-- 掃描指定包(將帶有@componet註解類自動定義為Spring bean) --> <context:componet-scan base-package="aop.demo"/> <!-- 配置一個切面 --> <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" value="greetingAroundAdvice"></property> <!-- 增強 --> <property name="pattern" value="aop.demo.GreetingImpl.good.*"></property> <!-- 切點(正則表示式) --> </bean> <!-- 配置一個代理 --> <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" value="greetingImpl"></property><!-- 目標類 --> <property name="interceptorNames" value="greetingAdvisor"></property><!-- 切面 --> <property name="proxyTargetClass" value="true"/> <!-- 代理目標類(預設為false,代理介面)--> </bean> |-- AOP自動代理(每一個類都需要配置切面太麻煩,因此需要自動生成代理) |-- 配置檔案-spring.xml <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="target" value="*Impl"></property><!-- 目標類 --> <property name="interceptorNames" value="greetingAroundAdvice"></property><!-- 增強 --> <property name="optimize" value="true"/> <!-- 是否對代理生成策略進行優化,預設是false --> </bean> *Impl -> 不清楚Bean實現了多少介面,不能代理介面,只能代理類。 |-- 匹配到目標類的指定方法 |-- 配置檔案-spring.xml <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <!-- <property name="target" value="*Impl">--></property><!-- 目標類 --> <!-- <property name="interceptorNames" value="greetingAroundAdvice"></property>--><!-- 增強 --> <property name="optimize" value="true"/> <!-- 是否對代理生成策略進行優化,預設是false --> </bean> --> <bean id="greetingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" ref="greetingAroundAdvice"></property> <!-- 增強 --> <property name="pattern" value="aop.demo.GreetingImpl.good.*"></property> <!-- 切點(正則表示式) --> </bean> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> <property name="optimize" value="true"/> <!-- 是否對代理生成策略進行優化,預設是false --> </bean> 總結: CGLib代理:建立代理速度慢,建立代理後執行速度快(系統初始化建立代理備用最佳) JDK動態代理:建立代理速度快,執行速度慢 |-- spring + AspectJ(Advisor) |-- 普通demo |-- @Aspect @Component public class GreetingAspect { @Arount("execution(* aop.demo.GreetingImpl.*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable { before(); Object result = pjp.proceed(); after(); return result; } public void before(){ sysout("Before"); } public void after(){ sysout("after"); } } |-- 配置檔案-spring.xml <!-- 掃描指定包(將帶有@componet註解類自動定義為Spring bean) --> <context:componet-scan base-package="aop.demo"/> <aop:aspect-autoproxy proxy-target-class="true" /> |-- 基於註解 |-- @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @Interface Tag { } |-- @Aspect @Component public class GreetingAspect { @Arount("@Annotation(aop.demo.Tag)") public Object around(ProceedingJoinPoint pjp) throws Throwable { ... } ... } |-- @Component public class GreetingImpl implements Greeting { @Tag @Override public void sayHello(String name){ sysout("Hello!" + name); } ... } |-- 實現引入增強 |-- @Aspect @Component public class GreetingAspect { @DelareParents(value="aop.demo.GreetingImpl",defaultImpl="ApologyImpl.class") private Apology apology; } |-- ApologyImpl implements Apology { @Override public void saySorry(String name){ sysout("Sorry!" + name); } main(String[] args){ ApplicationContext context = new ClassPathXmlApplicationContext("aop/demp/spring.xml"); Greeting greeting = context.getBean("greetingImpl"); greeting.sayHello("Jack"); Apology apology = (Apology) greeting; apology.saySorry("Jack"); } } |-- 基於配置 |-- 配置檔案-spring.xml <!-- 掃描指定包(將帶有@componet註解類自動定義為Spring bean) --> <context:componet-scan base-package="aop.demo"/> <beans ...> <bean id="greetingImpl" class="aop.demo.GreetingImpl" /> <bean id="greetingAspect" class="aop.demo.GreetingAspect" /> <aop:config> <aop:aspect ref="greetingAspect"> <aop:around method="around" pointcut="execution (* aop.demo.GreetingImpl.*(..))"/> </aop:aspect> </aop:config> </beans>View Code
4、開發aop框架
|-- 定義註解類: |-- @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @Interface Aspect { Class<? extends Annotion> value(); } |-- 搭建代理框架 |-- interface Proxy { 代理介面 // 執行鏈式代理:可將多個代理通過一條鏈子串起來,一個個地去執行,執行順序取決於新增到鏈上的先後順序 Object doProxy(ProxyChain proxyChain) throws Throwable; } |-- class ProxyChain // 代理鏈 |-- Class<?> targetClass; |-- Object targetObject; }-- Method targetMethod; |-- MethodProxy methodProxy; }-- Object[] methodParams; |-- List<Proxy> proxyList = new ArrayList<>(); |-- int proxyIndex=0; |-- ProxChain(Class<?> targetClass,Object targetObject,Method targetMethod,MethodProxy methodProxy,Object[] methodParams,List<Proxy> proxyList){ this.targetClass = targetClass; ... } |-- getMethodParams() -> return methodParams; |-- getTargetClass() -> return targetClass; |-- getTargetMethod() -> return targetMethod; |-- Object doProxyChain() throws throwable{ Object methodResult; if (proxyIndex < proxyList.size()){ methodResult = proxyList.get(proxyIndex++).doProxy(); } else { methodResult = methodProxy.invokeSuper(targetObject, methodParams); } return methodResult; } |-- 新增pom.xml依賴 <!-- cglib 依賴--> <grouId>cglib<groupId>... |-- class ProxyManger // 代理管理類 |-- <T> T createProxy(final Class<?> targetClass, final List<Proxy> proxyList){ return (T) Enhancer.create(targetClass, new MethodInterceptor(){ @Overrice public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy){ return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList); } }); } |-- public abstract calss AspectProxy implements Proxy { // 切面代理 @Override public final Object doProxy(ProxyChain proxyChain) throws throwable { Object result = null; Class<?> cls = proxyChain.getTargetClass(); Method method = proxyChain.getTargetMethod(); Object[] params = proxyChain.getMethodParams(); begin(); try { if (intercept(cls, method, params)){ before(cls, method, params); result = proxyChain.doProxyChain(); after(cls, method, params); } else { return proxyChain.doProxyChain(); } } catch(Exception e){ logger.error("proxy failure", e); error(cls, method, params, e); throw e; } finally { end(); } } public void begin(){ } public void end(){ } public boolean intercept(Class<?> cls, Method method, Object[] params) throws Throwable { return true; } public void before(Class<?> cls, Method method, Object[] params) throws Throwable { } public void after(Class<?> cls, Method method, Object[] params) throws Throwable { } public void error(Class<?> cls, Method method, Object[] params, Throwable e){ } } |-- @Aspect(Controller.class) ControllerAspect extends AspectProxy{ // 攔截Controller 所有方法 private long begin; @Override public void before(Class<?> cls, Method method, Object[] params) throws Throwable { begin = System.currentTimeMillis(); } @Override public void after(Class<?> cls, Method method, Object[] params) throws Throwable { sysout(System.currentTimeMillis()-begin); } } |-- BeanHelper { ... // 設定bean例項 public static void setBean(Class<?> cls, Object obj){ BEAN_MAP.put(cls, obj); } } |-- ClassHelper { ... // 獲取某父類(或介面)的所有子類(或實現類) public static Set<Class<?>> getClassSetBySuper(Class<?> superClass){ Set<Class<?>> classSet = new HashSet<Classs<?>(); for(Class<?> cls : CLASS_SET){ if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)){ classSet.add(cls); } } } // 獲取應用包名下帶有註解的所有類 public static Set<Class<?>> getClassSetByAnnotation(Class<? extends Annotation> annotionClass){ Set<Class<?>> classSet = new HashSet<Classs<?>(); for(Class<?> cls : CLASS_SET){ if (superClass.isAnnotationPresent(annotionClass)){ classSet.add(cls); } } } ... } |-- AopHelper { ... private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception { Set<Class<?>> targetClassSet = new HashSet<Class<?>>(); Class<? extends annotation> annotation = aspect.value(); if (annotation != null && !annotation.equals(Aspect.class)){ targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation)); } return targetClassSet; } private static Map<Class<?>>,Set<Class<?>>> createProxyMap() throws Exception { Map<Class<?>>,Set<Class<?>>> proxyMap = new HashMap<Class<?>>,Set<Class<?>>>(); Set<Class<?>> proxyClassSet = ClassHelper.getClassSetByAnnotation(AspectProxy.class); for(Class<?> proxyClass : proxyClassSet){ if (proxyClass.isAnnotationPresent(Aspect.class)){ Aspect aspect = proxyClass.getAnnotation(Aspect.class); Set<Class<?>> targetClassSet = createTargetClassSet(aspect); proxyMap.put(proxyClass, targetClassSet); } } return proxyMap; } private static Map<Class<?>,List<Proxy>> createTargetMap(Map<Class<?>>,Set<Class<?>>> proxyMap) throws Exception { Map<Class<?>,List<Proxy>> targetMap = new HashMap<Class<?>,List<Proxy>>(); for(Map.Entry<Class<?>>,Set<Class<?>>> proxyEntry : proxyMap.entrySet()){ Class<?> proxyClass = proxyEntry.getKey(); Set<Class<?> targetClassSet = proxyEntry.getValue(); for(Class<?> targetClass : targetClassSet){ Proxy proxy = (Proxy) targetClass.newInstance(); if (targetMap.contains(targetClass)){ targetMap.get(targetClass).add(proxy); } else { List<Proxy> proxyList = new ArrayList<Proxy>(); proxyList.add(proxy); targetMap.put(targetClass, proxyList); } } } } static { try { Map<Class<?>>,Set<Class<?>>> proxyMap = createProxyMap(); Map<Class<?>,List<Proxy>> targetMap = createTargetMap(proxyMap); for(Map.Entry<Class<?>,List<Proxy>> targetEntry : targetMap.etrySet()){ Class<?> targetClass =targetEntry.getKey(); List<Proxy> proxyList = targetEntry.getValue(); Object proxy = ProxyManager.createProxy(targetClass, proxyList); BeanHelper.setBean(targetClass, proxy); } } catch(Exception e){ Logger.error("aop failure", e); } } } |-- HelperLoader { public static void init(){ Class<?>[] classList = { ClassHelper.class, BeanHelper.class, AopHelper.class, IocHelper.class, ControllerHelper.class }; for(Class<?> cls : classList){ ClassUtil.loadClass(cls.getName(), true); } } }View Code