java设计模式之——代理模式

一、定义与类型:

》定义:为其他对象提供一种代理,以控制对这个对象的访问;

》代理对象在客户端和目标对象之间起到中介的作用;例如:我们通过房产中介租房。

》类型;结构型

二、适用场景:

》保护目标对象。比如不知道真实房东是谁

》增强目标对象。控制客户端对目标对象的访问

租房前草拟合同就相当于对目标对象进行增强,相当于spring AOP中的before

租房子相当于目标对象

而租房到期后,计算水电费等后续工作,就相当于Spring AOP中的after,后续增强

 

三、代理模式的优点:

》代理模式能将代理对象与真实被调用的目标对象分离;

》一定程度上降低了系统的耦合度,扩展性好;

》保护目标对象;客户端对象不会直接了解到目标对象信息

》增强目标对象

四、缺点:

》代理模式会造成系统设计中类的数目增加,即代理类的添加

》在客户端和目标对象之间增加一个对象,会造成请求处理速度变慢。压测、大批量测试、

多线程等会检测出该问题

》增加系统的复杂度

五、代理——扩展:

》静态代理:在代码中通过代理类显式地看到代理类

》动态代理:jdk中的动态代理只能对实现接口的类生成代理类。动态代理无法代理类,只能代理接口。jdk中的动态代理是在程序调用到代理类对象时,才由jvm动态创建一个代理类的class文件,进而产生对象等。另外一种case,如果一个接口中有两个方法,也写了这个接口的实现,若在接口实现(代理类)中增加了新方法,而接口中没有该方法,那新方法也是无法被代理的。

》CGLib代理:CGLib相较于动态代理,是说该代理方式可以代理类.CGLib就是针对类实现进行代理。该代理原理是,继承要代理的类,然后重写其中的方法,进而实现代理。因为该方案是通过继承实现的,所以受限于final修饰符的使用。因为final修饰类,则该类无法被继承。如果final修饰方法,方法不可被重写,则该方案无法使用。故特别注意final修饰符。

六、spring代理选择——扩展:

》当Bean有实现接口时,spring就会用jdk的动态代理。

》当Bean没有实现接口时,spring使用CGLib

》可以强制使用CGLib

        >在spring配置中加入:<aop:aspectj-autoproxy proxy-target-class="true"/>

七、代理速度对比——扩展:

CGlib是通过底层asm实现的,如果使用cglib代理,会比静态代理快

jdk的动态代理,在10000次运算时,jdk7/jdk8的动态代理速度比CGLib大约快20%

八、代理模式的相关设计模式:

》代理模式和装饰者模式:实现方案类似,但目标不同。装饰者模式是为对象加上行为,而

代理模式是控制访问,更加倾向于通过设置代理人的方式增强目标对象。增强目标对象的方式

一般是增强对象的行为

》代理模式和适配器模式:适配器模式主要考虑改变代理对象的接口,而代理模式不会改变代理对象的接口。

九、代码实践:

代码场景以添加订单到数据库为例,分基础最经典的三层dao  service 业务层为例

添加数据到数据库的代码为基础代码,然后分别使用静态代理和动态代理两种方式演示

代理模式的使用,来实现简单的spring框架中的aop原理讲解

共用代码:

package pattern.structural.Proxy;

/**
 * Created by Administrator on 2019/8/18.
 */
public class Order {
    private String orderInfo;
    //用于作为后面分库分表演示的一个判断属性
    private Integer userId;

    public String getOrderInfo() {
        return orderInfo;
    }

    public void setOrderInfo(String orderInfo) {
        this.orderInfo = orderInfo;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }
}

 

package pattern.structural.Proxy;


/**
 * Created by Administrator on 2019/8/18.
 */
public interface IOrderDao {
    int insertOrder(Order order);
}
package pattern.structural.Proxy;

/**
 * Created by Administrator on 2019/8/18.
 */
public class OrderDaoImpl implements IOrderDao {
    public int insertOrder(Order order) {
        System.out.println("添加order成功");
        return 1;
    }
}

 

package pattern.structural.Proxy;

/**
 * Created by Administrator on 2019/8/18.
 */
public interface IOrderService {
    int saveOrder(Order order);
}

 

package pattern.structural.Proxy;

/**
 * Created by Administrator on 2019/8/18.
 */
public class OrderServiceImpl implements IOrderService {
    private IOrderDao iOrderDao;//如果用spring自动注入,此处要添加相应注解
    public int saveOrder(Order order) {
        //Spring会自动注入,此处因为没有spring环境,就直接new对象了
        iOrderDao = new OrderDaoImpl();
        System.out.println("Service层调用Dao层添加order方法");
        return iOrderDao.insertOrder(order);
    }
}

 》》》静态代理模式演示:

package pattern.structural.Proxy.staticProxy;

import pattern.structural.Proxy.IOrderService;
import pattern.structural.Proxy.Order;
import pattern.structural.Proxy.OrderServiceImpl;

/**
 * Created by Administrator on 2019/8/18.
 */
public class OrderServiceStaticProxy {
    private IOrderService iOrderService;

    public OrderServiceStaticProxy(IOrderService iOrderService) {
        this.iOrderService = iOrderService;
    }
    public int saveOrder(Order order){
        beforeMethod(order);
        iOrderService = new OrderServiceImpl();
        int res = iOrderService.saveOrder(order);
        aftgerMethod();
        return res;
    }
    private void beforeMethod(Order order){
        //代理模式之增强目标对象,如下演示了,在此可以做比如为mysql数据库添加数据时,
        //可以在此进行分库分表的逻辑判断操作。此处只是简单示意。
        int userId = order.getUserId();
        int dbRouter = userId % 2;
        System.out.println("静态代理分配到[db"+dbRouter+"进行处理");

        System.out.println("静态代理 befor code");
    }
    private void aftgerMethod(){
        System.out.println("静态代理 after code");
    }

}
package pattern.structural.Proxy.staticProxy;

import pattern.structural.Proxy.Order;
import pattern.structural.Proxy.OrderServiceImpl;

/**
 * Created by Administrator on 2019/8/18.
 */
public class Test {
    public static void main(String[] args) {
        Order order = new Order();
        order.setUserId(1);
        OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy(new OrderServiceImpl());
        orderServiceStaticProxy.saveOrder(order);
    }
}

 

"D:\Program Files\Java\jdk1.8.0_102\bin\java" "-javaagent:D:\InteliijIDea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61656:D:\InteliijIDea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\Java\jdk1.8.0_102\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_102\jre\lib\rt.jar;E:\JavaDesignMode\target\classes" pattern.structural.Proxy.staticProxy.Test
静态代理分配到[db1进行处理
静态代理 befor code
Service层调用Dao层添加order方法
添加order成功
静态代理 after code

Process finished with exit code 0

 》》》动态代理演示:

package pattern.structural.Proxy.dynamicproxy;

import pattern.structural.Proxy.Order;

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

/**
 * Created by Administrator on 2019/8/18.
 */
public class OrderServiceDynamixProxy implements InvocationHandler {
    private Object target;

    public OrderServiceDynamixProxy(Object target) {
        this.target = target;
    }
    public Object bind(){
        Class cls = target.getClass();
        //如下第一个参数为代理类对象加载器,第二个为类的各个属性
        /** * @param   loader the class loader to define the proxy class
         * @param   interfaces the list of interfaces for the proxy class
         *          to implement
         * @param   h the invocation handler to dispatch method invocations to
         * */
        return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);

    }
    //proxy在这个方法中很少被使用method就是目标对象的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object argObject = args[0];
        beforeMethod(argObject);
        Object object = method.invoke(target,args);
        afterMethod();
        return object;
    }
    public void beforeMethod(Object object){
       int userId =0;
        System.out.println("动态代理 before code");
        if (object instanceof Order) {
            Order order = (Order) object;
            userId = order.getUserId();
        }
        int dbRouter = userId % 2;
        System.out.println("动态代理分配到[db}"+dbRouter+"处理");
    }
    private void afterMethod(){
        System.out.println("动态代理 after code");
    }
}
package pattern.structural.Proxy.dynamicproxy;

import pattern.structural.Proxy.IOrderService;
import pattern.structural.Proxy.Order;
import pattern.structural.Proxy.OrderServiceImpl;
import pattern.structural.Proxy.staticProxy.OrderServiceStaticProxy;

/**
 * Created by Administrator on 2019/8/18.
 */
public class Test {
    public static void main(String[] args) {
        Order order = new Order();
        order.setUserId(2);
        IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamixProxy(new OrderServiceImpl()).bind();
        orderServiceDynamicProxy.saveOrder(order);
    }
}

 

动态代理 before code
动态代理分配到[db}0处理
Service层调用Dao层添加order方法
添加order成功
动态代理 after code

Process finished with exit code 0

 

十、代理模式源码解析(jdk+spring+mybatis):

1、搜索 jdk中java.lang.reflect  

2、ProxyFactoryBean 核心方法getObject();

       jdkDynamicAopProxy 类

      CglibAopProxy 类

3、mybatis  MapperProxyFactory  newInstance()  MapperRegist

MapperProxy类 invoke方法

Configuration getMapper();

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值