参考的资料:
http://blog.csdn.net/jiuqiyuliang/article/details/38423811
http://www.360doc.com/content/14/0801/14/1073512_398598312.shtml
代理模式:由代理对象持有原对象。在代理对象中做的操作实际上都是由原对象来执行的。
1.代理模式可以动态在真实方法被调用前添加一些代码。
2.代理模式更加灵活,根据传入不同的真实对象,去执行不同的策略,达到同一个结果。
静态代理:
1.需要一个统一的接口,接口规定了要执行什么方法。
package com.liang.pattern;
public interface UserManager {
public void addUser(String userId,String userName);
public void delUser(String userId);
public void modifyUser(String userId,String userName);
public String findUser(String userId);
}
2.原对象实现接口
package com.liang.pattern;
public class UserManagerImpl implements UserManager {
public void addUser(String userId, String userName) {
try{
System.out.println("UserManagerImpl.addUser() userId-->>" + userId);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException();
}
}
public void delUser(String userId) {
System.out.println("UserManagerImpl.delUser() userId-->>" + userId);
}
public String findUser(String userId) {
System.out.println("UserManagerImpl.findUser() userId-->>" + userId);
return "于亮";
}
public void modifyUser(String userId, String userName) {
System.out.println("UserManagerImpl.modifyUser() userId-->>" + userId);
}
}
当然还可以由另一个实现
package com.liang.pattern;
public class UserManagerImpl2 implements UserManager {
........
}
3.代理对象实现接口,并且持有原对象。
可以看到代理类中所有的方法,实际上都是执行的原函数的方法
package com.liang.pattern;
public class UserManagerImplProxy implements UserManager {
private UserManager userManager; //持有原对象
public UserManagerImplProxy(UserManager userManager){
this.userManager = userManager;
}
public void addUser(String userId, String userName) {
//在真实的方法调用之前,加入其它操作,比如:
//记录日志等操作或打印输入参数
System.out.println("start-->>addUser() userId-->>" + userId);
try{
userManager.addUser(userId, userName);
//执行成功,打印成功信息
System.out.println("success-->>addUser()");
}catch(Exception e){
e.printStackTrace();
//失败时,打印失败信息
System.out.println("error-->>addUser()");
//throw new RuntimeException();
}
}
public void delUser(String userId) {
//同上,略
userManager.delUser(userId);
}
public String findUser(String userId) {
//同上,略
userManager.findUser(userId);
return null;
}
public void modifyUser(String userId, String userName) {
//同上,略
userManager.modifyUser(userId, userName);
}
}
4.客户端的调用
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl());
userManager.addUser("001","于亮");
//同样我们可以传入UserManagerImpl2,实现依赖注入
UserManager userManager = new UserManagerImplProxy(new UserManagerImpl2());
userManager.addUser("001","于亮");
**代理模式很灵活,但同时由于接口的关系,一种代理类,只能代理一组同样实现了该接口的真实类。这样可能造成代理类过多,爆炸。
动态代理
参考资料:http://blog.csdn.net/jiuqiyuliang/article/details/38423811
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调(根据传入的对象,以及参数)调用被代理对象的的方法(Object result=method.invoke(proxied,args))
如果我们在操作真实对象之前不做任何操作,或者都做统一的处理(比如加日志。),那么不管任何真实类都可以用一个动态代理类来操作,避免了代理类的爆炸
使用: