Java代理(带你搞懂JDK代理模式)

什么是代理?

定义:给目标对象提供一个代理对象,并用代理对象控制对目标对象的引用

使用代理目的:

①:功能增强:通过代理业务对原有业务进行增强

②:控制访问:通过代理对象的方式间接的访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性

实现代理的两种方式

一、静态代理

1.静态代理特点

①:代理类是自己手动实现的,需要自己去创建一个类

②:代理类所代理的目标类是固定的

2.利用接口实现静态代理

关于接口的方式,我们在实现接口的时候,目标类和代理类都必须实现目标接口当中所实现的方法,从某种意义上代理类就可以帮我们实现目标类当中的方法,并且代理类还可以有自己的扩展方法。

3.代码实现

首先先定义接口

public interface ByClothes {
	void clothes(String size);
}

定义目标对象

public class ClothesFactory implements ByClothes {
    public void clothes(String size) {

        System.out.println("已制定好一件大小为" + size + "的衣服");
    }
}

制造代理对象

/**
 * 代理类
 */
public class Proxy implements ByClothes {
    //被包含的真是对象
    private ClothesFactory clothesFactory = new ClothesFactory();

    // 对功能的增强
    @Override
    public void clothes(String size) {
        frontService();
        clothesFactory.clothes(size);
        endService();
    }
    //前置服务
    public void frontService(){
        System.out.println("店员服务");
    }
    //前置服务
    public void endService(){
        System.out.println("售后服务");
    }



}

测试类

public class Test {
    public static void main(String[] args) {
        Proxy p = new Proxy();
        p.clothes("xx");
    }
}

结果 

4.静态代理逻辑图

5.静态代理存在的问题

①:当目标类曾多时,代理类也需要增多,导致代理类的关系不便。

②:当接口当中的功能增多或者修改,都会影响实体类,违反开闭原则(程序对访问开放,对修改关闭)

二、动态代理

1.静态代理和动态代理的区别

静态代理需要我们手动的去创建代理对象,动态代理则是采用jdk提供的方法创建代理对象

2.动态代理的实现

①:jdk动态代理:使用java反射包当中的类和接口实现动态代理的功能

②:cglib动态代理:cglib是是第三方的工具库。其原理是继承,cglib通过继承目标类,创建他的子类,在子类当中重写父类的相关方法,实现功能的增强。

(1).jdk动态代理

新建接口

//接口的目的是告诉代理对象代理那个方法
public interface ByClothes {
    /**
     * 制造衣服的方法
     * @param size 衣服的大小
     */
    void clothes(String size);
}
public interface ByShoot {
    void byShoot(String size);
}

新建对应工厂

public class ClothesFactory implements ByClothes{
    public void clothes(String size){

        System.out.println("已制定好一件大小为"+size+"的衣服");
    }
}
public class ShootFactory implements ByShoot{

    @Override
    public void byShoot(String size) {

        System.out.println("已经为您生产出了尺码为"+size+"的鞋子");
    }

}

代理类

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


public class ProxyFactory implements InvocationHandler {

    private Object factory ; //被代理对象的引用

    public Object getFactory(){
        return factory;
    }

    public void setFactory(Object factory){
        this.factory = factory;
    }



    //反射执行方法
    //1.Object :jdk创建的代理类,无需赋值
    //2.Method : 目标类当中的方法,jdk提供,不需要赋值
    //3.Object[]:目标类当中的方法参数 ,jdk提供,不需要赋值
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        FrontService();
        method.invoke(factory,args);//执行目标类当中的方法
        endService();
        return null;
    }
    public void FrontService() {
        System.out.println("根据您的需求进行市场调研");
    }

    //前置服务
    public void endService() {
        System.out.println("为您提供一条龙的包办服务");
    }

    //该方法并不是固定的,但是内部的Proxy类的创建是核心

    /**
     * 1.ClassLoader loader : 类的加载器:像内存当中加载对象,使用反射的方式获取
     * 2.Class<?>[] interfaces:获取目标类的接口,使用反射的方式获取---------》方法
     * 3.InvocationHandler h:让代理类知道被代理的方法
     * @return
     */
    public Object getProxyInstance() {
        // TODO Auto-generated method stub
        return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
    }
}

代理类细节

①:InvocationHandler接口:里边只有一个invoke()方法

invoke()方法:表示我们要求代理对象要完成的功能

        1).调用并执行目标的方法

        2).功能增强,在目标对象调用时增强其功能

②:Proxy类:核心对象,其目的是创建道理对象

以前我们创建对象是new构造器,现在我们使用Proxy类的方法,代理new的使用

newProxyInstance()方法的作用是创建代理对象,其返回值就是代理对象

//ClassLoader loader:类的加载器,复杂向内存当中加载对象,使用反射的方式获取

// Class<?>[] interfaces:目标对象实现的接口,也是反射获取

//InvocationHandler h:代理类需要完成的功能 public static Object newProxyInstance(ClassLoader loader,

                                Class<?>[] interfaces,

                                 InvocationHandler h)

测试类 

public class Test {
    public static void main(String[] args) {
        ProxyFactory proxy = new ProxyFactory();

        ClothesFactory clothesFactory = new ClothesFactory();
        proxy.setFactory(clothesFactory);  //告诉了我们代理类要代理的类
        ByClothes ByClothes = (ByClothes) proxy.getProxyInstance();
        ByClothes.clothes("XXL");

        ShootFactory shootFactory = new ShootFactory();
        proxy.setFactory(shootFactory);
        ByShoot byShoot = (ByShoot) proxy.getProxyInstance();
        byShoot.byShoot("45");
    }
}

结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值