反射原理及动态代理模式用法

news/2024/5/19 4:41:16 标签: 反射, 动态代理, 静态代理

知识点整理

反射

了解反射用法:
反射
反射
练习

public class Servant {
    private int a;
    private String str;
    public Servant() {
    }
    public Servant(String string,int _a) {
    }
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public String getStr() {
        return str;
    }
}


public class Main {
    public static void main(String[] args) {
    System.out.println("-----------------反射基本使用-------------------");
//1获取类对象 3种方式
    Servant servant = new Servant();
    Class<?> clazz = servant.getClass(); //方式1
    Class<?> clazz1 = Servant.class; //方式2
    try {
        Class<?> clazz2 = Class.forName("Reflection.Servant"); //方式3
    }catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
//创建对象
    try {
    Class<?> clazz3 = Servant.class;
    Servant servant1 = (Servant)clazz3.getDeclaredConstructor().newInstance();
    servant1.setA(10);
    System.out.println(servant1.getA());
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
}
/*************************************************************************************/
System.out.println("获取构所有构造函数---------------");
    Class<?> clazz4 = Servant.class;
    Constructor[] constructors = clazz4.getDeclaredConstructors();
    for (Constructor constructor:constructors) {
        System.out.println(constructor);
    }
    try {
    System.out.println("获取指定构造函数---------------");
    Class<?> clazz5 = Servant.class;
    Constructor constructor = clazz5.getDeclaredConstructor(String.class,int.class);
    System.out.println(constructor);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }

/*************************************************************************************/
System.out.println("获取类中所有的方法---------------");
    Class<?> clazz6 = Servant.class;
    Method[] methods = clazz6.getMethods();
    for (Method method:methods) {
        System.out.println(method);
    }
System.out.println("获取指定方法----------------");
    try {
    Method method = clazz6.getDeclaredMethod("setA",int.class);
    method.setAccessible(true);
    System.out.println(method);
    method.setAccessible(false);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
/*************************************************************************************/
System.out.println("获取类中所有成员变量------------------");
    Class<?> clazz7 = Servant.class;
    Field[] fields = clazz7.getDeclaredFields();
    for (Field field:fields) {
        System.out.println(field);
    }
System.out.println("获取类中指定成员变量--------------");
    Class<?> clazz8 = Servant.class;
    try {
    Field field = clazz8.getDeclaredField("str");
    System.out.println(field);
    Servant servant1 = new Servant();
    field.setAccessible(true);
    field.set(servant1,"12345678");
    System.out.println(field.getName()+" "+servant1.getStr());
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    }
    }
}

代理模式

定义:代理模式就是给目标对象提供一个代理对象,并由代理对象控制目标对象的引用。通俗来说:就是我们生活中常见的中介。
目的:
(1)通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性;
(2)通过代理对象对原有的的业务增强。
代理模式分为静态代理动态代理

静态代理

抽象角色:
定义代理角色和真实角色的公共对外方法
真实角色:
实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
代理角色:
实现抽象角色,是真实的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
静态代理:程序在编译期间就确定了代理和被代理的关系

接口: Start
Start ->实现  RealStart
Start ->实现  ProxyStart 
ProxyStart 是代理类包含RealStart

public interface Start {
    public void bookTicket();
    public void Config();
    public void CollectMoney();
    public void sing();
}
public class RealStart implements Start{
    @Override
    public void bookTicket() {
        System.out.println("RealStart bookTicket");
    }
@Override
public void Config() {
    System.out.println("RealStart Config");
    }
@Override
public void CollectMoney() {
    System.out.println("RealStart CollectMoney");
    }
@Override
public void sing() {
    System.out.println("RealStart sing");
    }
}
public class ProxyStart implements Start {
    private Start start;
    public ProxyStart(Start _start) {
        start=_start;
}
@Override
public void bookTicket() {
    System.out.println("ProxyStart bookTicket");
}
@Override
public void Config() {
    System.out.println("ProxyStart Config");
}
@Override
public void CollectMoney() {
    System.out.println("ProxyStart CollectMoney");
}
@Override
public void sing() {
        start.sing();
    }
}
public static void main(String[] args) {
    System.out.println("-------------简单代理--------------");
    Start realStart = new RealStart();
    Start proxyStart = new ProxyStart(realStart);

    proxyStart.CollectMoney();
    proxyStart.bookTicket();
    proxyStart.sing();
}

动态代理

动态代理相比静态代理的优点:
只能通过接口来创建代理类,不能通过类来创建代理类
动态代理利用反射机制效率比静态代理低,在程序运行时才确定代理和被代理之间的关系

实现InvocationHandler(处理器接口) 方式实现:
步骤:
1.真实对象接口
2.创建真实对象 实现接口
3.创建对象 实现 InvocationHandler接口
4.通过 Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Shop.class},invocationHandler); 实现代理

参数:
ClassLoader 类加载去
Class<?>[] interfaces 代理类的接口
InvocationHandler 实现InvocationHandler的类

public interface Shop {
        void buy();
}

public class Real implements Shop {
        @Override
        public void buy() {
            System.out.println("--买东西--");
        }
}

public class Invocation implements InvocationHandler {
        public Shop shop;
        public Invocation(Shop _shop) {
            shop =_shop;
            }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("开始海外代购");
            Object object = method.invoke(shop,args);
            System.out.println("海外代购完成");
            return object;
        }
}

public class Main {
        public static void main(String[] args) {
            Shop shop = new Real();
            InvocationHandler invocationHandler = new Invocation(shop);

            Shop proxy = (Shop) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Shop.class},invocationHandler);
            proxy.buy();
        }
}



例如2public class MarkCompany implements InvocationHandler {
    private Object factory;//真实对象
    public void setFactory(Object factory) {
    this.factory = factory;
    }
    public Object getFactory() {
        return factory;
    }
    public Object getProxyInstance() {
    //参数1 真实对象的类加载器 参数2 真实对象的接口 参数3 被代理的InvocationHandler
        return Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object object = null;
        Before();
        object = method.invoke(factory,args);
        After();
        return object;
    }

    public void Before() {
        System.out.println("开始行动");
    }
    public void After() {
        System.out.println("行动完成");
    }
}

public interface Shop {
    public void shopeat();
}

public class Real implements Shop {
    @Override
    public void shopeat() {
    System.out.println("代购");
    }
}



public class Main {
    public static void main(String[] args) {
    Shop shop = new Real(); //真实对象
    MarkCompany markCompany = new MarkCompany();
    markCompany.setFactory(shop);

    //代理对象1
    Shop shop1 = (Shop) markCompany.getProxyInstance();
    shop1.shopeat();

    //代理对象2
    //代理对象3
    }
}

http://www.niftyadmin.cn/n/1035748.html

相关文章

Vue | 26 工具 - 单元测试

主要内容&#xff1a; 简单的断言写可测试的组件断言的异步更新 Vue CLI已经为单元测试构建了操作项&#xff0c;使用Jest或Mocha开箱即用。我们也提供了官方的单元测试库Vue Test Utils,为自定义配置提供了更为细节的指导。 简单的断言 你不必为了组件的可测试性提供任何特殊…

SAP ABAP收货或者货物移动(MIGO,MB11,MB1A)在保存时候的增强点

增强的BADI是&#xff1a;MB_DOCUMENT_BADI&#xff0c;特别要注意的是假如你是想在 点击保存按钮的时候根据生成的凭证号&#xff08;即表示这个增强点处凭证号已经生成&#xff09;&#xff0c;把某些数据更新到你的自建表的话&#xff0c;要用第二个方法MB_DOCUMENT_UPDATE,…

Vue | 27 工具 - TypeScript 支持

主要内容&#xff1a; JavaScript在官方的声明及推荐配置创建工程及编码的开发工具推荐基本用例演示基于类风格的Vue组件插件使用中的参数类型注释返回类型 Vue CLI提供了构建 TypeScript工具支持。在Vue的下一个主要版本&#xff08;3.x&#xff09;我们也计划更多的提供我们对…

android Timer TimerTask源码

知识点整理Timer1.Timer的使用2 Timer源码解析在jdk自带的库中,有两种技术可以实现定时任务。一种是使用Timer,另外一个则是ScheduledThreadPoolExecutor这篇先讲解TimerTimer 1.Timer的使用 private Timer timer new Timer();timer.scheduleAtFixedRate(new TimerTask() {O…

Vue | 28 工具 - 产品部署

主要内容&#xff1a; 打开生产模式的几种配置方式预编译模板提取组件CSS的方式追踪运行时错误 如果你使用Vue CLI以下大部分建议是默认可用的。如果你使用的是自定义的构建设置时&#xff0c;这章才是相关的。 打开生产模式 在开发阶段&#xff0c;Vue对于常见的错误和陷阱提…

Vue | 29 规模化 - 路由

官方路由 对于大多数单页面应用&#xff0c;推荐使用官方支持的vue-router library&#xff0c;对于更多的细节&#xff0c;查看vue-router的文档。 从零开始简单的路由 如果你仅仅需要一个非常简单的路由&#xff0c;但不需要包含一个完整功能的路由库&#xff0c;你可以像…

C++指针讲解

知识点整理1.指针基本使用2.*p (*p) *p *p 区别3指针常量 常量指针 指向常量常量指针3 野指针使用注意4通用指针5 指针的算术运算&#xff08;指针步长&#xff09;6 指针与数组6.1指针与一维数组6.1.1 一维数组函数传参6.2 指针与二维数组6.2.1 二维数组函数传参7 数组指针与指…

Vue | 30 规模化 - 状态管理

类Flux官方实现 由于多个状态分散在不同的组件和组件直接的交互中&#xff0c;大型应用常常变得复杂。为了解决这个问题&#xff0c;Vue提供了vuex&#xff1a;我们有受到Elm启发的状态管理库。它甚至集成进了vue-devtools&#xff0c;无需配置即可进行时光旅行调试。 React …