java设计模式之代理模式举例

来源:互联网 发布:晋城网络推广经理招聘 编辑:程序博客网 时间:2024/06/05 16:51

如:有一个添加用户的方法:add(),在添加之前和添加之后要做分别做两中日志记录。
1.静态代理:
    1-1.继承的写法:

//接口:package com.watermelon.statics.proxy;public interface UserService {    public void add();}
//添加用户的实现类package com.watermelon.statics.proxy;public class UserServiceImpl implements UserService{    @Override    public void add() {        System.out.println("新增add");    }}
//代理类package com.watermelon.statics.proxy;public class UserServiceProxy extends UserServiceImpl{    @Override    public void add() {        System.out.println("add 之前日志2");        System.out.println("add 之前日志1");        super.add();        System.out.println("add 之后日志1");        System.out.println("add 之后日志2");    }}
//测试方法package com.watermelon.statics.proxy;public class Main {    public static void main(String[] args) {        UserService userServiceProxy = new UserServiceProxy();        userServiceProxy.add();    }}
//测试结果//add 之前日志2//add 之前日志1//新增add//add 之后日志1//add 之后日志2

缺点:不够灵活,1.每次增加日志需修改代理类。2.若其他方法下需要同样的日志记录,则需要新增代理类。

    2-2.聚合的方式:类内部有其他类的变量。

//接口package com.watermelon.statics.proxy;public interface UserService {    public void add();}
//实现类package com.watermelon.statics.proxy;public class UserServiceImpl implements UserService{    @Override    public void add() {        System.out.println("新增add");    }}
//代理类1:日志1package com.watermelon.statics.proxy;public class UserServiceProxy2 implements UserService{    private UserService tagert;    public UserServiceProxy2(UserService tagert) {        super();        this.tagert = tagert;    }    @Override    public void add() {        System.out.println("add 之前日志1");        tagert.add();        System.out.println("add 之后日志1");    }}
//代理类2:日志2package com.watermelon.statics.proxy;public class UserServiceProxy3 implements UserService{    private UserService tagert;    public UserServiceProxy3(UserService tagert) {        super();        this.tagert = tagert;    }    @Override    public void add() {        System.out.println("add 之前日志2");        tagert.add();        System.out.println("add 之后日志2");    }}
//测试类package com.watermelon.statics.proxy;public class Main {    public static void main(String[] args) {        UserService userService = new UserServiceImpl();        UserServiceProxy2 userServiceProxy = new UserServiceProxy2(userService);        UserServiceProxy3 userServiceProxy3= new UserServiceProxy3(userServiceProxy);        userServiceProxy3.add();    }}

测试结果同上。
和继承的方式比:新增日志记录不用修改代理类源码,直接新增代理类。
缺点:若要给其他的方法新增日志记录,则还是需要新增更多的代理类。

2.jdk动态代理。

//接口package com.watermelon.de.proxy;public interface UserService {    public void add();}
//实现类package com.watermelon.de.proxy;public class UserServiceImpl implements UserService{    @Override    public void add() {        System.out.println("新增add");    }}
//代理工厂类 生成代理类 生成日志记录2代理类package com.watermelon.de.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class UserServiceProxyFactory1 implements InvocationHandler{    private Object tagert;    public MyTwoInvocationHandeler(Object tagert) {        super();        this.tagert = tagert;    }    public Object getProxy(){        ClassLoader loader = tagert.getClass().getClassLoader();        Class<?>[] interfaces = tagert.getClass().getInterfaces();        return Proxy.newProxyInstance(loader, interfaces, this);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        System.out.println("之前日志2");        Object result = method.invoke(tagert, args);        System.out.println("之后日志2");        return result;    }}
//代理工厂类 生成代理类 生成日志记录2代理类package com.watermelon.de.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class UserServiceProxyFactory2 implements InvocationHandler{    private Object tagert;    public MyTwoInvocationHandeler(Object tagert) {        super();        this.tagert = tagert;    }    public Object getProxy(){        ClassLoader loader = tagert.getClass().getClassLoader();        Class<?>[] interfaces = tagert.getClass().getInterfaces();        return Proxy.newProxyInstance(loader, interfaces, this);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {        System.out.println("之前日志2");        Object result = method.invoke(tagert, args);        System.out.println("之后日志2");        return result;    }}
//测试类User类package com.watermelon.de.proxy;public class Main {    public static void main(String[] args) {        UserService userService = new UserServiceImpl();        //UserServiceProxyFactory1  代理工厂类        UserServiceProxyFactory1  proxyFactory1 = new UserServiceProxyFactory1 (userService);        UserService userServiceproxy = (UserService) proxyFactory1.getProxy();        UserServiceProxyFactory2  proxyFactory2 = new UserServiceProxyFactory2(userServiceproxy);        UserService userServiceProxy1 = (UserService) proxyFactory2.getProxy();        userServiceProxy1.add();    }}
//测试结果之前日志2之前日志1新增add之后日志1之后日志2

在比如,我现在有个部门类有个update方法也要添加同样的两种日志记录

//部门接口package com.watermelon.de.proxy;public interface DepartmentService {    public int update();}
//实现类package com.watermelon.de.proxy;public class DepartmentServiceImpl implements DepartmentService{    @Override    public int update() {        System.out.println("修改 update");        return 1;    }}
//测试类package com.watermelon.de.proxy;public class Main {    public static void main(String[] args) {        DepartmentService departmentService = new DepartmentServiceImpl();        UserServiceProxyFactory1  proxyFactory1 = new UserServiceProxyFactory1 (departmentService);        DepartmentService departmentServiceProxy1 = (DepartmentService) proxyFactory1.getProxy();        UserServiceProxyFactory2  proxyFactory2 = new UserServiceProxyFactory2 (departmentServiceProxy1);        DepartmentService departmentServiceProxy2 = (DepartmentService) proxyFactory2.getProxy();        departmentServiceProxy2.update();    }}

结论:使用动态代理每种日志记录可以灵活配置,分开添加。没新增一种日志记录,只需要新增一种代理类的生成类。
    生成动态代理类的步骤:
        1.添加InvocationHandler接口。实现重写public Object invoke(Object proxy, Method method, Object[] args)方法。
            2.添加一个private Object tagert;变量、并重写带tagert变量的构造方法。
        3.新增一个返回代理类的方法;通过Proxy.newProxyInstance(loader, interfaces, this);方法返回代理类。

4.cglib动态代理
不用和jdk动态地理一样需要实现同样的接口。直接生成类的动态代理类。

package com.watermelon.cglibproxy;public class UserServiceImpl {    public void add()    {        System.out.println("add loading...");    }}

CglibFactory 代理工厂类

package com.watermelon.cglibproxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CglibFactory implements MethodInterceptor{    private Enhancer enhancer = new Enhancer();    public Object getProxy(Class clazz){        //设置创建子类的类        enhancer.setSuperclass(clazz);        enhancer.setCallback(this);        return enhancer.create();    }    /**     * 拦截所有目标类方法的调用     * obj  目标类的实例     * m   目标方法的反射对象     * args  方法的参数     * proxy代理类的实例     */    @Override    public Object intercept(Object obj, Method m, Object[] args,            MethodProxy proxy) throws Throwable {        System.out.println("日志开始...");        //代理类调用父类的方法        proxy.invokeSuper(obj, args);        System.out.println("日志结束...");        return null;    }}

测试方法:

public static void main(String[] args) {    UserServiceImpl userServiceImpl=  new UserServiceImpl();        CglibFactory cglibFactory = new CglibFactory();    UserServiceImpl userServiceImplProxy = (UserServiceImpl)cglibFactory.getProxy(userServiceImpl.getClass());        userServiceImplProxy.add();}

需要引入cglib-nodep-2.2.jar

原创粉丝点击