Java設計模式之代理模式☞再談JDK的動態代理

前言java

爲何要再談,由於動態代理是aop編程的核心。後面分析spring aop的源代碼的最重要的理論基礎。spring

再談動態代理編程

首先動態代理須要哪些角色呢?ide

1.抽象角色。這個抽象角色必須爲接口。函數

2.具體角色。這個具體角色必須實現抽象接口。this

3.IAdvice接口和BeforeAdviceImple實現類。spa

4.InvocationHandler的實現類。這個類爲動態代理的Handler類。設計

5.產生代理的接口,抽象類,工廠類。代理

6.場景類Client。code

 

1.咱們先新增一個抽象角色ISubject接口。這個接口定義一個方法handle。代碼以下所示:

1 package com.example.pattern.proxy.dynamic.second; 2 
3 public interface ISubject { 4 
5     public void handle(); 6 }

第5行,定義接口handle。

 

2.定義一個具體角色RealSubject。這個角色實現ISubject接口。代碼以下所示:

1 package com.example.pattern.proxy.dynamic.second; 2 
3 public class RealSubject implements ISubject { 4  @Override 5     public void handle() { 6         System.out.println("-----handle-----"); 7  } 8 }

第6行,處理handle業務邏輯。

 

3.新增一個通知事件的接口和實現類,代碼以下所示。

1 package com.example.pattern.proxy.dynamic.second; 2 
3 public interface IAdvice { 4 
5     public void execute(); 6 }
1 package com.example.pattern.proxy.dynamic.second; 2 
3 public class BeforeAdviceImpl implements IAdvice { 4  @Override 5     public void execute() { 6         System.out.println("執行前置通知"); 7  } 8 }

 第6行,定義execute業務前置邏輯。

 

4.再來新增一個InvocationHandler的默認處理器。

 1 package com.example.pattern.proxy.dynamic.second;  2 
 3 import java.lang.reflect.InvocationHandler;  4 import java.lang.reflect.Method;  5 
 6 public class DefaultInvocationHandler implements InvocationHandler {  7 
 8     private Object instance = null;  9 
10     public DefaultInvocationHandler(Object instance) { 11         this.instance = instance; 12  } 13 
14  @Override 15     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 16         return method.invoke(this.instance, args); 17  } 18 }

 第8行,定義被代理對象的實例。

 

5.產生代理的接口,抽象類,實現類。

1 package com.example.pattern.proxy.dynamic.second; 2 
3 import java.lang.reflect.InvocationHandler; 4 
5 public interface IDynamicProxy<T> { 6 
7     public <T> T newProxyInstace(Class<T> clazz, InvocationHandler h); 8 
9 }
package com.example.pattern.proxy.dynamic.second; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public abstract class AbstractDynamixProxy<T> implements IDynamicProxy<T> { public abstract void before() ; @Override public T newProxyInstace(Class clazz, InvocationHandler h) { this.before(); ClassLoader classLoader = clazz.getClassLoader(); Class[] interfaces = clazz.getInterfaces(); return (T)Proxy.newProxyInstance(classLoader, interfaces, h); } }
 1 package com.example.pattern.proxy.dynamic.second;  2 
 3 public class SubjectDynamicProxyImpl<ISubject> extends AbstractDynamixProxy<ISubject>{  4 
 5  @Override  6     public void before() {  7 
 8         IAdvice advice = new BeforeAdviceImpl();  9  advice.execute(); 10 
11  } 12 }

①有接口,有抽象類,有具體方法?我爲何要這麼設計呢?爲何不是直接寫在場景類中呢?那若是有10個場景須要,是否是在10出都要寫相同或者類似的代碼呢?若是一旦有改動,那麼,改動的工做量不說,容易產生潛伏性bug。 接口是聲明主要用途,抽象類是用來提取公共代碼。具體類是爲了構建個性化代碼,好比before方法。 就是一個典型的鉤子函數。說了這麼多,這難道不是模板模式的應用嗎?

②IDynamicProxy<T>這是一個泛型接口。T能夠是一個接口或者普通類,具體是什麼類型,由場景來類決定,這不就實現了代碼很是靈活的複用嗎?同時不也是提升了可讀性嗎?

6.增長場景類Client。

 1 public class Client {  2 
 3     public static void main(String[] args) {  4         ISubject subject = new RealSubject();  5 
 6         InvocationHandler invocationHandler = new DefaultInvocationHandler(subject);  7 
 8         IDynamicProxy<ISubject> dynamicProxy = new SubjectDynamicProxyImpl();  9         ISubject proxyInstance = dynamicProxy.newProxyInstace(subject.getClass(), invocationHandler); 10 
11  proxyInstance.handle(); 12  } 13 }

執行的結果以下圖所示:

1 執行前置通知 2 -----handle-----

 

咱們爲何要使用IAdvice呢。這已經引入了aop中的一些術語,在什麼地方執行什麼行爲,是否是能夠理解 在鏈接點執行什麼通知呢?這已是一個簡單的面向切面過程的示例,Advice是什麼呢?也正是咱們要去切入的類。

相關文章
相關標籤/搜索