zoukankan      html  css  js  c++  java
  • jQuery火箭图标返回顶部代码

    0. 前言

    学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,它利用的是反射机制,依赖注入就不用多说了,而对于Spring的核心AOP来说,使用了动态代理,所以本篇随笔就是对java的动态代理进行一个回顾

    1. 代理模式

    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等

    2. 静态代理

    由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。缺点:代理类和被代理类编译期间都写死了,不够灵活

    package com.zad.java;
    
    /**
     *
     * 静态代理举例
     * 代理类和被代理类编译期间都写死了,不够灵活
     */
    
    interface smile{
        void produceCloth();
    }
    
    /**代理类**/
    class ProxyClothFactory implements smile{
    
        private smile factory;//用被代理类对象进行实例化
    
        public ProxyClothFactory(smile factory){
            this.factory = factory;
        }
    
        @Override
        public void produceCloth() {
            System.out.println("你真的");
            factory.produceCloth();
            System.out.println("是不是");
        }
    
    }
    
    //被代理类
    class realsmile implements smile{
    
        @Override
        public void produceCloth() {
            System.out.println("很开心");
        }
    }
    
    
    public class StaticProxyTest {
        public static void main(String[] args) {
            //创建被代理类对象
            realsmile real = new realsmile();
            //创建代理类对象
            ProxyClothFactory proxyClothFactory = new ProxyClothFactory(real);
            proxyClothFactory.produceCloth();
        }
    }

    3. 动态代理

    Java反射提供了一种类动态代理机制,可以通过代理接口实现类来完成程序无侵入式扩展。

    Java动态代理主要使用场景:

    1. 统计方法执行所耗时间。
    2. 在方法执行前后添加日志。
    3. 检测方法的参数或返回值。
    4. 方法访问权限控制。
    5. 方法Mock测试。

    创建动态代理类会使用到java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。java.lang.reflect.Proxy主要用于生成动态代理类Class、创建代理类实例。proxy类实现了java.io.Serializable接口

    InvocationHandler接口

    java.lang.reflect.InvocationHandler接口用于调用Proxy类生成的代理类方法,该类只有一个invoke方法,那么也必须要实现该方法,入口参数Object proxy即为要被代理的对象,method为被调用的方法,args为代理实例的方法参数数组,若没参数则为null

     proxy类

     该类中我们用的最多的就是 newProxyInstance 这个方法,这个方法的作用就是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义

    loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
    
    interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
    
    h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
    package com.zad.java;
    
    import org.omg.CORBA.SystemException;
    import org.omg.CORBA.portable.InputStream;
    import org.omg.CORBA.portable.InvokeHandler;
    import org.omg.CORBA.portable.OutputStream;
    import org.omg.CORBA.portable.ResponseHandler;
    import sun.awt.AWTAccessor;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 动态代理举例
     *
     *
     * **/
    
    interface Human{
        String getBelief();
        void eat(String food);
    }
    //被代理类
    class SuperMan implements Human{
    
        @Override
        public String getBelief() {
            return "I believe I can fly!";
        }
    
        @Override
        public void eat(String food) {
            System.out.println("我喜欢吃"+food);
        }
    }
    
    /**
     *
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     *
     * 实现动态代理需要解决的问题:
     * 问题1:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
     * 问题2:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a
     */
    
    class ProxyFactory{
        //调用此方法,返回一个代理类的对象,解决了问题1
        public static Object getProxychInstance(Object obj){//obj:被代理类的对象
            MyInvocationHandler handler = new MyInvocationHandler();
            handler.bind(obj);
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
        }
    }
    class MyInvocationHandler implements InvocationHandler {
        private Object obj;
        public void bind (Object obj){
            this.obj = obj;
        }
    
        //当我们通过代理类的对象,调用方法a,就会自动调用如下方法:invoke()
        //将被代理类要执行的方法a的功能就声明在invoke()中
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //method:就是代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
            Object returnValue = method.invoke(obj, args);
            return returnValue;
        }
    
    }
    public class ProxyTest {
        public static void main(String[] args) {
            SuperMan superMan = new SuperMan();
            Human proxyInstance = (Human) ProxyFactory.getProxychInstance(superMan);
            proxyInstance.getBelief();
            proxyInstance.eat("麻辣烫");
    
        }
    }

    cglib代理

    这里我们先简单说一下这两种代理方式最大的区别,JDK动态代理是基于接口的方式,换句话来说就是代理类和目标类都实现同一个接口,那么代理类和目标类的方法名就一样了,这种方式上一篇说过了;CGLib动态代理是代理类去继承目标类,然后重写其中目标类的方法啊,这样也可以保证代理类拥有目标类的同名方法

    cglib特点:

    1. 可以代理没有实现接口的类
    2. 可以在运行期扩展java类与实现java接口,被许多aop框架所使用,例如spring AOP和dynaop提供方法的interception拦截

    cglib和动态代理的区别

    • 使用动态代理必须实现接口
    • cglib无需实现接口,达到代理类无侵入

     引入cglib的jar包(https://repo1.maven.org/maven2/cglib/cglib/3.2.5/cglib-3.2.5.jar)

    <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.5</version>
    </dependency>

    男的写了

  • 相关阅读:
    URAL 1998 The old Padawan 二分
    URAL 1997 Those are not the droids you're looking for 二分图最大匹配
    URAL 1995 Illegal spices 贪心构造
    URAL 1993 This cheeseburger you don't need 模拟题
    URAL 1992 CVS
    URAL 1991 The battle near the swamp 水题
    Codeforces Beta Round #92 (Div. 1 Only) A. Prime Permutation 暴力
    Codeforces Beta Round #7 D. Palindrome Degree hash
    Codeforces Beta Round #7 C. Line Exgcd
    Codeforces Beta Round #7 B. Memory Manager 模拟题
  • 原文地址:https://www.cnblogs.com/kuaile1314/p/14209445.html
Copyright © 2011-2022 走看看