您的位置:首页 > 其它

23种设计模式之代理模式

2017-09-12 14:48 369 查看
代理模式:即Proxy Pattern,23种常用的面向对象软件的设计模式之一。

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式能够解决什么问题呢?

1、监听被代理的类里面的方法什么时候执行

2、动态的给某一个方法添加新的功能

代理模式分类:

静态代理

能够使用静态代理首先得有一个前提条件:被代理的类必须要实现接口。

实现步骤:

(1)、首先要被代理类要实现接口

(2)、代理类必须要和 被代理的类实现相同的接口

(3)、在我们的代理类中实例化我们的被代理类的对象

(4)、重写接口中的方法

(5)、在我们调用被代理类中的方法的时候 可以进行拓展了

接口类 IUserDao.java

public interface IUserDao {
public  void  method1();
}


被代理类:UserDao.java

public class UserDao implements IUserDao {
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("这是方法1");
}
}


代理类:UserDaoProxy

public class UserDaoProxy implements IUserDao {
private UserDao userDao;
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("开启事物");
userDao.method1();
System.out.println("结束事物");
}
public UserDaoProxy(UserDao userDao) {
super();
this.userDao = userDao;
}
public UserDaoProxy() {
this.userDao =new UserDao();
}
}


动态代理

动态代理 又名JDK代理,也就是说这种代理模式是在JDK中提供了相应的实现类。动态代理的原理生成了子类的对象,可以避免静态代理中代理类接口过多的问题。

动态代理也有一个前提:就是我们被代理的类也要实现接口(或者本身就是接口)。

代码实现

接口和被代理类和上面的一样

测试类:Test.java

public static void main(String[] args) {
// TODO Auto-generated method stub
UserDao userDao=new UserDao();
//在JDk中提供了一个类  这个类  Proxy
/**
* 第一个参数:就是当前代理的类的class对象.getClassLoader
* 第二个参数:如果被代理的是类 class对象.getInterfaces()
* 第二个参数如果代理的是接口的话 那么应该这样写 new Class[]{代理接口.class}
* 第三个参数:就是用来监听我们的代理类里面方法的执行的
*/
IUserDao userDao2=(IUserDao) Proxy.newProxyInstance(UserDao.class.getClassLoader(), UserDao.class.getInterfaces(), new InvocationHandler() {
/**
* 中断我们的方法的执行的
* 你可以这样理解 就是调用我们的被代理类里面的方法的时候会自动被拦截下来  你可以确定是否执行
* proxy:生成的代理对象
* method:当前你请求的方法(反射里面的)
* args:这个就是你执行这个方法需要的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//申明一个返回值
Object returnValue=null;
//下面就可以对你要监听的方法进行处理
//例如:判定我们执行的方法是不是method1()方法
String methodName=method.getName();
if("method1".equals(methodName)){
//是不是要在执行方法之前添加事务
System.out.println("打开事务");
//执行这个方法 第一个参数;就是被代理的这个对象
returnValue=method.invoke(userDao, args);
//在方法执行之后 关闭事务
System.out.println("关闭事务");
}else{  //这个表示的是当前请求的不是save方法
//下面表示的是没有调用save这个方法
returnValue=method.invoke(userDao, args);
}
return returnValue;
}
});
//查看userDao2的结果
userDao2.method1();
}


cglib代理

这种代理方式需要导入包
cglib-2.2.2.jar

asm-3.3.1.jar

UserDao.java

public class UserDao {
public void test(){
System.out.println("数据保存成功...");
}
}


UserDaoProxy.java

public class UserDaoProxy {
private UserDao userDao=null;
public UserDaoProxy() {
userDao=new UserDao();
}
public UserDaoProxy(UserDao userDao) {
this.userDao=userDao;
}
/*
* 该方法返回被代理对象
*/
public Object getObject() {
//第一步:申明这个enhancer对象
Enhancer enhancer=new Enhancer();
//第二步:设置该代理类的对象的父类
enhancer.setSuperclass(userDao.getClass());
//设置监听父类里面的方法的回调
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] arg2,MethodProxy arg3) throws Throwable {
//获取方法名
String methodName = method.getName();
//设置返回的结果
Object returnValue=null;
//判定是否是我们的监听的方法
if("test".equals(methodName)) {
System.out.println("执行事务");
returnValue=method.invoke(userDao, arg2);
System.out.println("结束事务");
}else {
//如果不是,就直接放行
returnValue=method.invoke(userDao, arg2);
}
return returnValue;
}
});
return enhancer.create();
}
}


还可以写成这样

public class UserDaoProxy implements MethodInterceptor{
private UserDao userDao=null;
public UserDaoProxy() {
userDao=new UserDao();
}
public UserDaoProxy(UserDao userDao) {
this.userDao=userDao;
}
public Object getObject() {
//声明一个enhancer对象
Enhancer enhancer=new Enhancer();
//设置UserDao为该代理对象的父类
enhancer.setSuperclass(userDao.getClass());
//监听父类的方法
enhancer.setCallback(this);
return enhancer.create();
}
//监听方法
@Override
public Object intercept(Object obj, Method method, Object[] arg2,MethodProxy arg3) throws Throwable {
//获取方法名
String methodName = method.getName();
//返回结果
Object returnValue=null;
//判定方法是否是我们监听的方法
if("test".equals(methodName)) {
System.out.println("开始事务");
returnValue=method.invoke(userDao, arg2);
System.out.println("结束事务");
}else{
returnValue=method.invoke(userDao, arg2);
}
return returnValue;
}}


测试类

public static void main(String[] args) {
// TODO Auto-generated method stub
UserDaoProxy userDaoProxy=new UserDaoProxy(new UserDao());
UserDao userDao=(UserDao) userDaoProxy.getObject();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息