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是什么呢?也正是咱们要去切入的类。

相关文章
相关标签/搜索