Java simply implements an AOP through JDK dynamic proxy

Keywords: Java Spring

First of all, because I haven't studied the source code of AOP in spring yet, I just know its function roughly, so I want to realize a first look manually. I think I will gain more when I study the source code later.

Implement: To do a method that adds annotations before executing, you can execute another method first. Similar to AOP (@Brfore), students who do not understand can go to Baidu, this side only to make a simple reality.

First, prepare an interface IEat as your task, such as eat():

public interface IEat {
    void eat();
}

Then two classes to implement this interface, one is our main method (the original function is immutable, here we customize a @DoPre annotation similar to @Before) Eat, the other is our proxy class MyProxy, proxy class also need to implement the Invocation Handler interface, and put cook() method in front of invoker() method (this method is unclear students can go to Baidu). Next, he's here to implement Eat's eat() method, which is equivalent to the way I need to add in front of me. I have to cook before I eat.

public class Eat implements IEat {
    @DoPre
    @Override
    public void eat() {
        System.out.println("eateateat");
    }
}
public class MyProxy implements InvocationHandler, IEat {
    private Object object;

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

    public MyProxy(Object object) {
        this.object = object;
    }

    @Override
    public void eat() {
    }

    private void cook() {
        System.out.println("cooking");
    }
}

@ DoPre annotations don't do anything specific, just as a tag, remember that adding @Retention (Retention Policy.RUNTIME) means that the runtime can find annotations through reflection:

@Retention(RetentionPolicy.RUNTIME)
public @interface DoPre {}

Finally, the main method acts as the initiator, and the init() method is responsible for scanning the method with this @DoPre annotation under the current package. The initialization here is very simple, without traversing other packages and subpackages, all simplification can optimize many places by itself:

public class Test {
    public static IEat eat;

    //start
    public static void main(String[] args) {
        init();
        eat.eat();
    }

    private static void init() {
        Class clazz = Test.class;
        String packagePath = clazz.getResource("").getPath();
        String packagename = clazz.getPackage().getName();
        File file = new File(packagePath);
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            assert files != null;
            for (File file1 : files) {
                try {
                    StringBuilder stringBuilder = new StringBuilder(packagename);
                    stringBuilder.append(".").append(file1.getName());
                    String s = stringBuilder.toString().replace(".class", "");
                    Class clazz1 = Class.forName(s);
                    Method[] methods = clazz1.getMethods();
                    for (Method method : methods) {
                        Annotation[] annotations = method.getDeclaredAnnotations();
                        for (Annotation annotation : annotations) {
                 //Find a way to annotate
if (annotation.toString().contains("DoPre")) {
                   //Pass in the proxy instance clazz1.newInstance() IEat proxy
= (IEat) Proxy.newProxyInstance(Test.class.getClassLoader(), MyProxy.class.getInterfaces(), new MyProxy(clazz1.newInstance()));
                   //Injected object eat
= proxy; } } } } catch (Exception e) { e.printStackTrace(); } } } } }

I am also a new person, so I hope you will forgive me, the code is not perfect, more like a demonstration of this function, but the core idea should be similar, and the simpler it is, the faster it can be understood by students, we should learn more ideas!

Posted by zzlong on Sat, 12 Oct 2019 03:49:57 -0700