首页 > 代码库 > 模糊的概念(2)
模糊的概念(2)
这种概念的模糊,还是因为当时在看书或者学习某一个知识点的时候,没有能够把这个知识变为自己的东西,停留在比较浅层次的理解的基础上面,没有能够真正的运用上面,就像那些笑话中所说的一样,“这些道理臣妾都明白,可就是过不好日子”。道理光是明白肯定是过不好日子的,明白了,理解了,最重要的是想办法去应用,把学到的知识最终归到自己的知识体系里面,这样才算是真正的明白,才有过好日子的可能。
继续说设计模式:代理的设计模式,以前的理解,比较的高效,认为代理就是请求来临的时候,代理对象首先执行,然后在去执行被代理对象的方法。如果按照这种大而化之的理解,那么组合类里面的任何一个调用都是代理模式了。
还是首先是简单的UML:
真正的对象和代理对象都会实现这个接口,然后在调用的时候,调用的是代理的对象,然后代理的对象再去调用真正的对象。
// 抽象角色:abstract public class Subject { abstract public void request();}// 真实角色:实现了Subject的request()方法public class RealSubject extends Subject { public RealSubject() { } public void request() { System.out.println( " From real subject. " ); }}// 代理角色:public class ProxySubject extends Subject { // 以真实角色作为代理角色的属性 private Subject realSubject; public ProxySubject(Subject realSubject) {this.realSubject = realSubject } // 该方法封装了真实对象的request方法 public void request() { preRequest(); realSubject.request(); // 此处执行真实对象的request方法 postRequest(); } ...}// 客户端调用:RealSubject real = new RealSubject();Subject sub = new ProxySubject(real);Sub.request();
还有一种方式是继承的方式:
核心的代码是:
//dosomething before super.doOperation() //dosomething after
- 采用父类的调用,不用接口的这种方式。
一般的情况下,真是的对象应该增加访问的限制,例如:不能够在外部的访问。
说到了代理模式,JDK实现了一个动态代理的模式,为什么会有这个动态代理,因为上面虽然实现了代理,但是每一个类一个代理的话,代码呈现臃肿,并且也不符合同一个功能对应一块或者一个类,或者说抽象封装的设计理念,所以就有了JDK的动态代理,其UML是:
具体的代码:
package regularExpression.current;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;interface ISubject { public void showName(String name);}class RealSubject implements ISubject { @Override public void showName(String name) { System.out.println(name+"闪亮登场"); }}class LogHandler implements InvocationHandler { Object target=null; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result=null; //调用目标对象方法前的逻辑 System.out.println("下面有一个大人物要出现"); //调用目标对象的方法,这句代码将代理与目标类联系了起来 method.invoke(target, args); //调用目标对象方法后的逻辑 System.out.println("大家鼓掌欢迎"); return result; }}public class Client { /** * @param args */ public static void main(String[] args) { LogHandler logHandler=new LogHandler(); logHandler.setTarget(new RealSubject()); //创建代理对象 ISubject proxySubject=(ISubject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(), logHandler); System.out.println("-------JDK Proxy-------------"); proxySubject.showName("委座"); }}
看到这个方法:java.lang.reflect.Proxy.newProxyInstance(ClassLoader, Class<?>[], InvocationHandler) 应该能够推出来:
JDK的动态代理,必须的要实现了接口的类才能够有动态代理,不然的话,在类Proxy的方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
无法建立代理的实例,就无法代理了,但是cglib可以,具体的UML为:
可以看到的是RealSubject 不需要实现一个接口,
class LogIntercept implements MethodInterceptor { Object target=null; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { Object result=null; //调用目标对象方法前的逻辑 System.out.println("下面有一个大人物要出现"); //调用目标对象的方法,这句代码将代理与目标类联系了起来 arg3.invoke(target, arg2); //调用目标对象方法后的逻辑 System.out.println("大家鼓掌欢迎"); return result; }}
调用的方式:
LogIntercept logIntercept=new LogIntercept(); logIntercept.setTarget(new RealSubject()); RealSubject proxySubject1=(RealSubject )Enhancer.create(RealSubject.class, logIntercept); System.out.println("-------CBLIB-------------"); proxySubject1.showName("委座");
这也就能够理解spring提供两种代理方式的原因:
目标对象有没有实现接口Spring都会选择使用CGLIB代理。所以在默认情况下,如果一个目标对象如果实现了接口,Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象,可以通俗的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出j ava.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现任何接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类。
代理模式这样算是到一个阶段,这样才能够穿起来,理清一个点。
模糊的概念(2)