JAVA internship job search-reflection mechanism and dynamic agent

introduction

Before the emergence of reflection, when we have a java class, we cannot use the private structure in the class outside of the class, for example, we cannot call the private constructor, private method, etc. But after reflection, we can call any structure of this class, including private.

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionTest {

    @Test
    public void test1(){
        Person p = new Person("tom",23);
        p.show();
    }


    @Test
    public void test2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取类对象
        Class<Person> personClass = Person.class;
        //2.获取类对象的构造器
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        Object tom = constructor.newInstance("Jerry", 23);
        //3.获取类方法
        Method show = personClass.getDeclaredMethod("show");
        show.invoke(tom);

        //反射的特殊功能,可以调用私有的类结构
        Constructor<Person> cons1 = personClass.getDeclaredConstructor(String.class);
        cons1.setAccessible(true);
        Person wanglei = cons1.newInstance("wanglei");
        wanglei.show();


    }

}

Reflection and singleton mode

The singleton pattern privatizes the constructor, and I hope that only one instance of this class needs to be created. By that time, reflection is to solve the problem of whether it can be used. The singleton mode is to suggest your writing. They are not in conflict.

Understanding of java.lang.Class

Class as the source of reflection

(1) Class loading process: After the program is compiled by javac.exe, one or more bytecode files will be generated. Class ends, each java class corresponds to a bytecode file, through java.exe interpretation to run a certain The bytecode file of the mian method. This is equivalent to loading this bytecode file into memory. This process is called class loading. The class recorded in memory is called the runtime class, and this runtime class is used as an instance of Class. In other words, an instance of Class corresponds to a runtime class.

Four ways to get Class objects

//方式一:调用运行时类的属性:.class
        Class clazz1 = Person.class;
        System.out.println(clazz1);
        //方式二:通过运行时类的对象,调用getClass()
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);

        //方式三:调用Class的静态方法:forName(String classPath)
        Class clazz3 = Class.forName("com.atguigu.java.Person");
//      clazz3 = Class.forName("java.lang.String");
        System.out.println(clazz3);

        System.out.println(clazz1 == clazz2);
        System.out.println(clazz1 == clazz3);

        //方式四:使用类的加载器:ClassLoader  (了解)
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("com.atguigu.java.Person");
        System.out.println(clazz4);

        System.out.println(clazz1 == clazz4);

Three steps:

Load: add the class file of the class to the memory and create a Class object. This process is completed by the class loader

Link: Ensure that the information contained in the byte stream of the Class file meets the requirements of the current virtual machine and does not jeopardize the security of the virtual machine itself.

Initialization: When compiling and generating a class file, the compiler will generate two methods to add to the class file, one is the class initialization method clinit, and the other is the instance initialization method init. clinit refers to the class constructor, the main role is to perform in the initialization phase of the class loading process, the execution content includes static variable initialization and static block execution.

 

 

introduction

The proxy pattern is one of 23 design patterns, which is more important knowledge. The more important AOP (Aspect Oriented Programing) in the Spring framework is also based on dynamic proxy.

Agent's understanding

As for the understanding of agents, let me give an example: 20 years ago, the way we wanted to buy a Lenovo computer was: we went to Lenovo ’s factory, and the factory sold us computers, and provided after-sales services.

In the development of these decades, some dealers have appeared. They bought goods from the Lenovo factory and sold them to us. When the computer broke, we also went to the dealer ’s shop to find him, and then he went to the factory, so we The connection with the factory was actually broken.

In 2020, if we want to buy a laptop, we will go directly to large distributors such as Tmall, Suning, and JD.com to buy a computer. If there is a problem, we will return the product without reason for 7 days.

Here we are the client Client, those dealers are also called agents, and Lenovo factories are called agents. Such a process is an agent.

Dynamic proxy

The characteristics of dynamic proxy: byte code is created and loaded at any time, and loaded at any time

The role of dynamic agents: enhance the method without modifying the source code

Classification of dynamic agents: 2 types, one is dynamic agent based on interface, and the other is dynamic agent based on subclass

Interface-based dynamic proxy

The Proxy class implementation provided by JDK requires that the proxy class implement at least one interface. The implementation process is as follows

(1) First create the Lenovo class and implement an interface

package com.alibaba200408.动态代理;

public class Lenovo implements ILenovo {
    @Override
    public void sale(Double money) {
        System.out.println("拿到"+money+"元,电脑发货");
    }

    @Override
    public void afterService(Double money) {
        System.out.println("拿到"+money+"元,售后服务开始");

    }
}

The code is very simple, only two methods are involved, one is to sell the computer and the other is to repair the computer.

The code of the interface is as follows

package com.alibaba200408.动态代理;

public interface ILenovo {

    void sale(Double money);

    void afterService(Double money);
}

(2) Instantiate a dynamic proxy object and call methods through the proxy object

package com.alibaba200408.动态代理;

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

public class Client {
    public static void main(String[] args) {

        //联想厂家
        ILenovo lenovo = new Lenovo();


        //创建代理对象
        ILenovo proxyInstance = (ILenovo) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(),
                lenovo.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * invoke方法的作用是调用任何被代理对象的方法都会被这个invoke方法拦截
                     *  proxy:表示当前代理对象的引用
                     *  method:表示当前正在执行的方法
                     *  args:表示当前执行的方法的参数
                     *
                     *  返回值就是当前方法的返回值
                     */

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //提供增强的代码
                        Double money = (Double) args[0];
                        if ("sale".equals(method.getName())){
                            method.invoke(lenovo, money * 0.8);
                        }else {
                            method.invoke(lenovo,args);
                        }

                        return null;
                    }
                });

        proxyInstance.afterService(10000.0);

    }
}

Dynamic agent based on subclass

This implementation requires that the proxy class cannot be final, because the final modified class cannot have subclasses, and secondly, this method requires a third-party cglib. I will not repeat them here.

Published 111 original articles · Like 60 · 70,000 + views

Guess you like

Origin blog.csdn.net/Haidaiya/article/details/105512739