代理设计模式的核心含义在于一个业务操做除了真实实现以外,也须要有代理支持,代理负责全部与真实操做有关的辅助性功能实现,而真实主题只负责核心业务操做。java
代理使用分析:数据库
在传统编写DAO程序操做过程之中,一直是存在有一个问题的,业务层的真实功能是调用数据层,可是发如今咱们以前写的代码之中,业务层除了要调用数据层组织数据以外,还要负责数据库的打开和关闭。设计模式
范例:定义业务层接口ide
1
2
3
4
|
package com.zmcheng.Demo;
public interface Service {
public void print() throws Exception;
}
|
范例:定义真实主题类this
1
2
3
4
5
6
7
8
9
|
package com.zmcheng.Demo;
public class ServiceImpl implements Service {
@Override
public void print() throws Exception {
System.out.println("********操做前的准备:打开数据库链接*******");
System.out.println("********操做数据层的若干操做*******");
System.out.println("********操做后的收尾:关闭数据库链接*******");
}
}
|
以上是最先的设计思路,可是若是说如今结合代理设计模式来看,实现就很是槽糕了,由于全部的核心业务操做业务与辅助业务都同时写在了一个方法里。必须解决这样的问题。spa
范例:设计一个静态代理类设计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.zmcheng.Demo;
public class SeriverProxy implements Service {
Service service;
public SeriverProxy(Service service){
this.service = service;
}
public void pre() throws Exception{
System.out.println("********操做前的准备:打开数据库链接*******");
}
public void end() throws Exception{
System.out.println("********操做后的收尾:关闭数据库链接*******");
}
public void print() throws Exception {
this.pre();
this.service.print();
this.end();
}
}
|
范例:真实主题实现类代理
1
2
3
4
5
6
7
|
package com.zmcheng.Demo;
public class ServiceImpl implements Service {
@Override
public void print() throws Exception {
System.out.println("********操做数据层的若干操做*******");
}
}
|
而在使用的时候应该也经过工厂类取得接口实例化对象。code
范例:定义serviceFactory对象
1
2
3
4
5
6
|
package com.zmcheng.Demo;
public class serviceFactory {
public static Service getServiceInstance(){
return new SeriverProxy(new ServiceImpl());
}
}
|
此时继续编写客户端,客户端依然是经过工厂取得接口实例化对象,客户端不会关心是代理主题仍是真实主题,只是它知道,利用你这个工厂的方法就能够取得Seriver接口,就能够操做了。
范例:编写客户端
1
2
3
4
5
6
7
|
package com.zmcheng.Demo;
public class Test {
public static void main(String[] args) throws Exception{
Service service = serviceFactory.getServiceInstance();
service.print();
}
}
|
这个时候的代理发生了做用,也就是说在实际的环境之中,代理设计模式应该和工厂设计模式联合起来,这样客户端在操做的时候就不会有任何的不适应感。
动态代理设计模式:
使用代理模式能够有效的抽取出核心业务与辅助业务,可是回顾整个项目的开发过程里面,可能会存在几百个业务层接口。但是这个时候全部的代理层的功能发现都同样,都只是负责真实主题业务调用,以及打开关闭数据库。若是每个业务层接口都编写一个代理,基本上的表现:代理也是折磨人的。因此必须想办法让一个代理类能够负责全部真实主题的操做。
若是想要实现动态代理设计模式,必须有一个类来实现java.lang.reflect InvocationHandler接口。此接口有一个方法:
Object invoke(Object proxy, Method method,Object[] args) throws Throwable
实际上invoke()这个方法是属于反射调用的方法,证实动态代理也属于反射调用,而在invoke方法里面参数:
Object proxy:表示要代理的对象;
Method method:表示要操做的方法;
Object args[]:方法调用时传递的参数。
若是要想让代理设计真正可使用,必须有一个代理类对象产生,而这个代理类对象的产生能够经过java.lang.reflect.Proxy类完成,而在Proxy类里面有一个取得代理对象的实例化方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
throws IllegalArgumentException
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.zmcheng.Demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ServiceProxy implements InvocationHandler {
private Object target=null;
public Object getProxy(Object obj){
this.target = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
public void prepare(){
System.out.println("********操做前的准备:打开数据库链接*******");
}
public void end() throws Exception{
System.out.println("********操做后的收尾:关闭数据库链接*******");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object retValue = method.invoke(this.target, args);
return retValue;
}
}
|
下篇博客将对剖析动态代理类的原理。