动态代理

动态代理

1、代理模式

定义

给目标对象提供一个代理对象,并且由代理对象控制对目标对象的引用。

目的

  • 通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性。
  • 通过代理对象对原有的业务增强。

在这里插入图片描述

代理模式三要素

  • 接口:约定了真实对象和代理对象的公共接口
  • 真实对象:代理对象锁代理的真实对象,最终被引用的对象。
  • 代理对象:包含真实对象,从而可以操作真实对象,相当于访问者与真实对象之间的中介者。不提供服务,只是服务的搬运工,所以要包含真实对象。

在这里插入图片描述

代码

//接口,约定了服务提供者的行为
interface ManToolsFactory
{
    void saleManTools(String size);
}
class AaFactory implements ManToolsFactory
{

    @Override
    public void saleManTools(String size)
    {
        System.out.println("根据您的需求,为您定制了一个size为:"+size+"的女模特");

    }
}

//代理对象,包含真实的对象,为真实对象的服务进行增强,和真实对象继承同一个接口
class Lison implements ManToolsFactory
{
    //被包含的真实的对象
    private ManToolsFactory factory;

    public Lison(ManToolsFactory factory)
    {
        super();
        this.factory = factory;
    }


    @Override
    public void saleManTools(String size)
    {
        doSomethingBefore();  //前置增强
        factory.saleManTools(size);
        doSomethingAfter();    //后置增强

    }

    private void doSomethingBefore()
    {
        System.out.println("精美包装,快递一条龙服务");
    }

    private void doSomethingAfter()
    {
        System.out.println("提供售后服务");
    }
}

public class Client
{
    public static void main(String[] args) {
        ManToolsFactory manToolsFactory = new AaFactory();
        Lison lison = new Lison(manToolsFactory);
        lison.saleManTools("A");
    }

}

输出

精美包装,快递一条龙服务
根据您的需求,为您定制了一个size为:A的女模特
提供售后服务

几个设计原则(一共6个?)

  • 单一设计原则:一个类或者一个接口只负责唯一一项职责,尽量设计出功能单一的接口。
  • 依赖倒转原则:高层模块不应该依赖低层模块具体实现,解耦高层与低层,既面向接口编程,当实现发生变化的时候,只需要提供新的实现类,不需要修改高层模块的代码。
  • 开放-封闭原则:程序对外扩展开放,对修改关闭,换句话说,当需求发生变化的时候,我们可以通过添加新模块来满足要求,而不是修改原来的实现代码来满足新的需求。

其他人有其他类别的代购需求找我的话,我就要创建新的接口,实现。。。违反了开闭原则。

2、动态代理

静态代理在有其他需求的时候需要增加很多代码,也不符合开闭原则。
所以有了动态代理。
在这里插入图片描述每来一个人需要代购东西,这个公司就派相关领域的帮忙,也就是生成动态代理对象。

在这里插入图片描述
在这里插入图片描述

Proxy(由Proxy生成的所有的动态代理都是它的子类)

Proxy可以理解成调度器,下面是Proxy类的注释的第一句。

{@code Proxy} provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

通过newInstance生成动态代理对象。

InvocationHandler

接口只有一个方法,invoke方法。

public interface InvocationHandler 
{
   public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable;
}

通过invoke进行业务增强,Method是反射得来的。

动态代理代码

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

class LisonCompany implements InvocationHandler
{
    //被代理对象
    private Object factory;

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

    public Object getFactory()
    {
        return factory;
    }

    public Object getProxyInstance()
    {
        return Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),this);
    }




    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        doSomethingBefore();
        Object ret = method.invoke(factory, args);
        doSomethingAfter();
        return ret;
    }

    public void doSomethingBefore()
    {
        System.out.println("包装精美,快递一条龙服务。");
    }
    public void doSomethingAfter()
    {
        System.out.println("为您提供售后。");
    }
}
//接口,约定了服务提供者的行为
interface ManToolsFactory
{
    void saleManTools(String size);
}
class AaFactory implements ManToolsFactory
{

    @Override
    public void saleManTools(String size)
    {
        System.out.println("根据您的需求,为您定制了一个size为:"+size+"的女模特");

    }
}


interface WomanToolsFactory
{
    void saleWomenTools(int height);
}
class BbFactory implements WomanToolsFactory
{

    @Override
    public void saleWomenTools(int height)
    {
        System.out.println("根据您的需求,为您定制了一个身高为:"+height+"的男模特");

    }
}
class Client
{
    public static void main(String[] args) {
        //1、日本有个公司生产你需要的产品
        ManToolsFactory factory1 = new AaFactory();
        //2、Lison成立了一个代购公司
        LisonCompany lisonCompany1 = new LisonCompany();
        //3、现在有人找我代购
        lisonCompany1.setFactory(factory1);
        //
        ManToolsFactory proxyInstance1 = (ManToolsFactory)lisonCompany1.getProxyInstance();  //内部调用Proxy的newProxyInstance方法
        proxyInstance1.saleManTools("A");
        
        //1、日本有个公司生产你需要的产品
        WomanToolsFactory factory2 = new BbFactory();
        //2、Lison成立了一个代购公司
        LisonCompany lisonCompany2 = new LisonCompany();
        lisonCompany2.setFactory(factory2);

        WomanToolsFactory proxyInstance2 = (WomanToolsFactory)lisonCompany2.getProxyInstance();  //内部调用Proxy的newProxyInstance方法
        proxyInstance2.saleWomenTools(180);
        
    }

}

输出

包装精美,快递一条龙服务。
根据您的需求,为您定制了一个size为:A的女模特
为您提供售后。
包装精美,快递一条龙服务。
根据您的需求,为您定制了一个身高为:180的男模特
为您提供售后。

3、深入理解动态代理

博客链接

博客链接
在这里插入图片描述

可以看出动态代理类proxyInstance1的类名叫做 $ Proxy0,proxyInstance2的类名叫做$Proxy2

类的生命周期

在这里插入图片描述
加载、验证、准备、解析、初始化、使用、卸载

动态代理没有源文件,忽略掉了从源文件到字节码的编译,直接就生成了java字节码,这样的话java字节码来源直接在内存中生成。

newProxyInstance里面有一行

/*
* Look up or generate the designated proxy class.
* 查询或者生成代理类。
*/
Class<?> cl = getProxyClass0(loader, intfs);

getProxyClass0源码

private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) 
                                           {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

get方法
先尝试从缓存中拿到代理类,拿不到的话就生成一个代理类。

public V get(K key, P parameter) 
{
    Objects.requireNonNull(parameter);//判断parameter是否为Null

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) 
    {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    //上面表示尝试从缓存中拿到代理,如果没有拿到的话,则会生成一个代理类。
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}

apply方法

public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

        Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
        for (Class<?> intf : interfaces) 
       	{
            /*
             * Verify that the class loader resolves the name of this
             * interface to the same Class object.
             */
            Class<?> interfaceClass = null;
            try 
            {
                interfaceClass = Class.forName(intf.getName(), false, loader); //拿到接口的class对象
            } 
            catch (ClassNotFoundException e) 
            {
            }
            if (interfaceClass != intf) 
            {
                throw new IllegalArgumentException(
                    intf + " is not visible from class loader");
            }
            /*
             * Verify that the Class object actually represents an
             * interface.
             */
            if (!interfaceClass.isInterface()) //判断它是不是一个接口
            {
                throw new IllegalArgumentException(
                    interfaceClass.getName() + " is not an interface");
            }
            /*
             * Verify that this interface is not a duplicate.
             */
            if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) //判断是否有冲突
            {
                throw new IllegalArgumentException(
                    "repeated interface: " + interfaceClass.getName());
            }
        }

        String proxyPkg = null;     // package to define proxy class in

        /*
         * Record the package of a non-public proxy interface so that the
         * proxy class will be defined in the same package.  Verify that
         * all non-public proxy interfaces are in the same package.
         */
        for (Class<?> intf : interfaces)   //判断所有方法是否加了public修饰符
        {
            int flags = intf.getModifiers();
            if (!Modifier.isPublic(flags)) {
                String name = intf.getName();
                int n = name.lastIndexOf('.');
                String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                if (proxyPkg == null) {
                    proxyPkg = pkg;
                } else if (!pkg.equals(proxyPkg)) {
                    throw new IllegalArgumentException(
                        "non-public interfaces from different packages");
                }
            }
        }

        if (proxyPkg == null) {
            // if no non-public proxy interfaces, use com.sun.proxy package
            proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }

        /*
         * Choose a name for the proxy class to generate.
         */
        long num = nextUniqueNumber.getAndIncrement();
        String proxyName = proxyPkg + proxyClassNamePrefix + num;

        /*
         * Generate the specified proxy class.
         */
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
            proxyName, interfaces);//在内存中生成Java字节码
        try 
        {
            return defineClass0(loader, proxyName,
                                proxyClassFile, 0, proxyClassFile.length);
        } catch (ClassFormatError e) {
            /*
             * A ClassFormatError here means that (barring bugs in the
             * proxy class generation code) there was some other
             * invalid aspect of the arguments supplied to the proxy
             * class creation (such as virtual machine limitations
             * exceeded).
             */
            throw new IllegalArgumentException(e.toString());
        }
    }
}

private static final String proxyClassNamePrefix = “$Proxy”; //类生成规则前缀

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);//在内存中生成Java字节码

在字节码文件反编译会看到生成的动态代理类继承Proxy接口,会调用InvocationHandler的invoke方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值