设计模式之代理模式

一、概念

二、静态代理

三、动态代理

四、Cglib代理


一、概念

代理模式—种设计模式,提供了对目标对象的另外的访问方式即通过代理访问目标对象

好处:1、可以在目标对象实现的基础上,增加额外的功能的操作

         2、扩展目标对象的功能

二、静态代理

保存数据到数据库Dao直接保存

添加事务

要求:代理对象,要实现与目标对象一样的接口

优点:可以做到不修改目标对象功能前提下,对目标对象扩展。

缺点∶因为代理对象需要实现与目标对象相同的接口,会有很多代理类一旦接口增加方法,目标对

象与代理对象都需要维护

解决方式:代理工厂,动态代理

package com.iotek.staticPackage;

public interface UserDao {
    public void save();
}
package com.iotek.staticPackage;

/**
 * @Author:目标对象
 * @CreateTime: 2023-01-05  12:28
 */
public class UserDaoImpl implements UserDao{
    @Override
    public void save() {
        System.out.println("-----------------数据已保存到数据库-----------------");
    }
}
package com.iotek.staticPackage;

/**
 * @Author:代理对象静态代理方式)
 * @CreateTime: 2023-01-05  12:30
 */
public class UserDaoProxy implements UserDao{
    private UserDao userDao;

    public UserDaoProxy(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void save() {
        System.out.println("开始事务");
        userDao.save();
        System.out.println("提交事务");
    }
}
package com.itoek.staticPackage;

/**
 * @Author:
 * @CreateTime: 2023-01-05  12:35
 */
public class Test {
    public static void main(String[] args) {
        /*目标对象*/
        UserDao userDao = new UserDaoImpl();
        /*代理对象*/
        UserDao userDaoProxy = new UserDaoProxy(userDao);
        userDaoProxy.sava();
    }
}

 

三、动态代理

代理对象不需要实现接口

代理对象生成,使用到JDKAPI,动态的在内存中创建代理对象

动态代理,也叫JDK代理,接口代理

 public static Object newProxyInstance(ClassLoader loader,//指定当前目标对象的使用类的加载器
                                          Class<?>[] interfaces,//目标实现的接口类型
                                          InvocationHandler h//事件处理器)

目标对象一定要实现接口,否则不能使用动态代理

class $Proxy0 implements XXX

package com.iotek.dynamic;

public interface UserDao {
    public void save();
    public void update();
}
package com.iotek.dynamic;

/**
 * @Author:目标对象
 * @CreateTime: 2023-01-05  12:28
 */
public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("-----------------数据已保存到数据库-----------------");
    }

    @Override
    public void update() {
        System.out.println("-----------------数据已修改-----------------");
    }
}
package com.iotek.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Author:
 * @CreateTime: 2023-01-05  12:45
 */
public class ProxyFactory {
    private Object target;//目标对象

    public ProxyFactory(Object target) {
        this.target = target;
    }
    /*生成代理对象*/
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),//目标对象加载器
                target.getClass().getInterfaces(),//目标兑现所实现的接口
                new InvocationHandler() {//事件处理器
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开始事务");
                        Object result = method.invoke(target,args);//调用目标对象方法
                        System.out.println("结束事务");
                        return result;
                    }
                }
        );
    }
}
package com.iotek.dynamic;

/**
 * @Author:
 * @CreateTime: 2023-01-05  12:43
 */
public class Test {
    /*目标对象*/
    public static void main(String[] args) {
        /*目标对象*/
        UserDao userDao = new UserDaoImpl();
        /*代理对象 class com.sun.proxy.$Proxy0内存中动态生成的代理对象*/
        UserDao proxy = (UserDao) new ProxyFactory(userDao).getProxyInstance();
        proxy.save();
        proxy.update();
        System.out.println(proxy.getClass());
    }

}

 

四、Cglib代理

有一个目标对象,没有接口

子类代理。在内存中构建一个子类对象从而实现对目标对象的扩展

Cglib许多AOP框架使用

步骤︰
        引用.jar文件---Spring Core包中包含

        在内存中动态创建目标对象的子类

        目标对象不可以是final

        目标对象方法是final、static,则不会拦截

在Spring AOP编程中

        如果加入容器中的目标对象有实现接口,用IDK代理

        如果目标对象没有有实现接口,用cglib代理

package com.iotek.cglib;

/**
 * @Author:目标对象
 * @CreateTime: 2023-01-05  12:28
 */
public class UserDaoImpl {
    public void save() {
        System.out.println("-----------------数据已保存到数据库-----------------");
    }

    public void update() {
        System.out.println("-----------------数据已修改-----------------");
    }
}
package com.iotek.cglib;

import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @Author:cglib子类代理工厂(对Use人Dao在内存中动态创建一个代理)
 * @CreateTime: 2023-01-05  14:16
 */
public class ProxyFactory implements MethodInterceptor {
    /*目标对象*/
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    /*代理对象*/
    public Object getProxyInstance(){
        /*1、工具类*/
        Enhancer enhancer = new Enhancer();
        /*2、设置父类*/
        enhancer.setSuperclass(target.getClass());
        /*3、设置回调*/
        enhancer.setCallback(this);
        /*4、创建代理对象*/
        return enhancer.create();
    }

    /*方法拦截器接口*/
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        /*执行目标对象的方法*/
        System.out.println("开始事务");
        Object resultValue = method.invoke(target,objects);
        System.out.println("结束事务");
        return resultValue;
    }



}
package com.iotek.cglib;

/**
 * @Author:
 * @CreateTime: 2023-01-05  14:38
 */
public class Test {
    public static void main(String[] args) {
        /*目标对象*/
        UserDaoImpl userDaoImpl = new UserDaoImpl();
        /*代理对象*/
        UserDaoImpl proxy = (UserDaoImpl) new ProxyFactory(userDaoImpl).getProxyInstance();
        proxy.save();
        proxy.update();
        System.out.println(proxy.getClass());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杪&秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值