1.代理模式和静态代理
代理模式
- Proxy Pattern, 23个经典模式的一种,又称委托模式
- 为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问
- 外界不用直接访问目标对象,而是访问代理对象,由代理对象再调用目标对象
- 代理对象中可以添加监控和审查处理
静态代理
- 代理对象持有目标对象的句柄
- 所有调用目标对象的方法,都调用代理对象的方法
- 代理类和被代理类应该共同实现一个接口,或者是共同继承某个类
- 对每个方法,需要静态编码(理解简单,但代码繁琐)
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
| public interface Subject{ public void request(); }
class SubjectImpl implements Subject{ @Override public void request(){ System.out.println("I am dealing the request."); } }
class StaticProxy implements Subject{ private Subject subject; public StaticProxy(Subject subject){ this.subject = subject; } @Override public void request(){ System.out.println("PreProcess"); subject.request(); System.out.println("PostProcess"); } }
public class StaticProxyDemo { public static void main(String args[]){ SubjectImpl subject = new SubjectImpl(); StaticProxy p = new StaticProxy(subject); p.request(); } }
|
2.动态代理
sequenceDiagram
participant 客户端
participant 代理对象
participant 代理处理器
participant 目标对象
客户端->>代理对象:调用方法
代理对象->>代理处理器:转发代理处理器
Invoke()方法
代理处理器->>目标对象:判断Method
调用目标对象的方法
目标对象->>代理处理器:返回结果
代理处理器->>代理对象:返回结果
代理对象->>客户端:返回结果
代理处理器
- 持有目标对象的句柄
- 实现InvocationHandler接口
- 实现invoke方法
- 所有的代理对象方法调用,都会转发到invoke方法来
- invoke的形参method,就是指代理对象方法的调用
- 在invoke内部,可以根据method,使用目标对象不同的方法来响应请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class ProxyHandler implements InvocationHandler{ private Subject subject; public ProxyHandler(Subject subject){ this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("====before===="); Object result = method.invoke(subject, args); System.out.println("====after===="); return result; } }
|
代理对象
- 根据给定的接口,由Proxy类自动生成的对象
- 类型 com.sun.proxy.$Proxy0,继承自java.lang.reflect.Proxy
- 通常和目标对象实现同样的接口(可另实现其他的接口)
- 实现多个接口
- 接口的排序非常重要
- 当多个接口里面有方法同名,则默认以第一个接口的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| SubjectImpl realSubject = new SubjectImpl();
ProxyHandler handler = new ProxyHandler(realSubject);
Subject proxySubject = (Subject)Proxy.newProxyInstance (SubjectImpl.class.getClassLoader(), SubjectImpl.class.getInterfaces(), handler);
proxySubject.request();
|
3.AOP编程
- AOP:Aspect Oriented Programming
面向切面编程 vs 面向对象编程
- 面向对象:将需求功能划分为不同的、独立,封装良好的类,并让它们
通过继承和多态实现相同和不同行为。 - 面向切面:将通用需求功能从众多类中分离出来,使得很多类共享一个
行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可
1 2 3 4 5 6 7 8
| //aops.xml配置文件示例 <aops> <aop> <method>washHand</method> <type>before</type> <method>eat</method> </aop> </aops>
|
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 60 61 62 63 64 65 66 67 68 69 70
| public static void initXml(){ XmlReader.readXml("aops.xml"); ResourceListener.addListener("E:/java/source/PMOOC04-03/"); }
public static void main(String[] args) throws Exception{ Main.initXml();
Person action = new PersonImpl(); ProxyHandler mh = new ProxyHandler(action); ClassLoader cl = Main.class.getClassLoader(); Class<?> proxyClass = Proxy.getProxyClass(cl, new Class<?>[]{Person.class}); Person proxy = (Person) proxyClass.getConstructor(new Class[]{InvocationHandler.class}). newInstance(new Object[]{mh});
while(true){ proxy.eat(); try{ Thread.sleep(3000); } catch(Exception e){ e.printStackTrace(); } } }
public class ProxyHandler implements InvocationHandler { static String beforeMethod = ""; static String afterMethod = ""; private Person receiverObject; public ProxyHandler(Person object){ this.receiverObject = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(beforeMethod!=null&&beforeMethod.length()>0){ ClassLoader cl = ProxyHandler.class.getClassLoader(); Class<?> c = cl.loadClass(receiverObject.getClass().getName()); Method m=c.getMethod(beforeMethod); Object obj = c.newInstance(); m.invoke(obj); } Object result = method.invoke(receiverObject, args); if(afterMethod!=null&&afterMethod.length()>0){ method.invoke(receiverObject, args); ClassLoader cl = ProxyHandler.class.getClassLoader(); Class<?> c = cl.loadClass(receiverObject.getClass().getName()); Method m=c.getMethod(afterMethod); Object obj = c.newInstance(); m.invoke(obj); } return result; } }
|
面向切面编程
- 一个概念/规范,没有限定语言
- 不是取代OOP编程,而是OOP的补充,和数据库的触发器有点相似
- 主要内容
- Aspect :配置文件,包括一些Pointcut和相应的Advice
- Joint point:在程序中明确定义的点,如方法调用、对类成员访问等
- Pointcut:一组joint point, 可以通过逻辑关系/通配符/正则等组合起来,定义了相应advice将要发生的地方
- Advice:定义了在pointcut处要发生的动作,通过before/after/around/来关联
- weaving:advice代码在具体joint point的关联方式
Java的AOP实现