java beginner's dynamic security agent

Preface: As security officers, agents are a lot of people use, what is the dynamic proxy java in it? In fact, java in the "dynamic" means that the use of reflection, so the agent is based on a dynamic reflection of the agency model.

Summary:

Acting is a common design pattern, its purpose is to provide a proxy to control access to an object to other objects. Delegate class class agents responsible for preprocessing message, message filtering and forwarding messages, and the message is performed after the delegate class performs the subsequent processing. In order to maintain the consistency of behavior, the proxy class and delegate class typically implement the same interface, so it seems both visitors without the slightest difference. By proxy class that the middle layer, can effectively control direct access to the delegate object can be well hidden and protected by the delegate class objects, but also set aside space for the implementation of different control strategies, so as to obtain a more in design flexibility. Java dynamic proxy mechanism in a clever way to practice a near-perfect design agency model.

 
First, a simple code examples to look at the application of dynamic proxies
Declare an interface subject, and then declare a class that implements this interface realSubject
subject Interface
public interface subject {
    void simpleSubject();
}

realSubject implementation class

public class realSubject implements subject{
    public void simpleSubject(){
        System.out.println("this is simpleSubject");
    }

}

Each object has a realSubject this simpleSubject interfaces, but if you want an object at runtime dynamic attach some hardSubject function, how to do it? We hardSubject and additional features (or some of the additional information) is achieved by implementing a proxy object on the proxy object. Proxy.newProxyInstance implementations are generated by a proxy object, the proxy object while generating the proxy object to bind a Handler, i.e. the call handler processor (of InvocationHandler) object.

First, to achieve a proxyHandler in front of or behind the original interface method to add hardSubject function (function here that may not be accurate)

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


public class proxyHandler implements InvocationHandler {
    private realSubject subject;
    public proxyHandler(realSubject subject){
        this.subject = subject;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("I'am the added hardSubject1"); method.invoke(subject); System.
out.println("I'am the added hardSubject2"); return null; } }

View InvocationHandler interface source code annotations can know that it is the function: when the original object is called proxy interface method, binds InvocationHandler execution method defined.

 

Then we write a test class to instantiate a proxy object

proxyTest test class

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

public class proxyTest {
    public static void main(String[] args){
        realSubject rs = new realSubject();
        InvocationHandler h = new proxyHandler(rs);
        Class clazz = rs.getClass();
        subject s =  (subject)Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),h);
        s.simpleSubject();
        System.out.println(s.getClass());
    }
}

Proxy method newProxyInstance three parameters, namely realSubject class loader, interfaces, and we define an object instance proxyHandler

 Look at the source code:

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

I bolded the part of the code that is a key part of the first step in the use of reflection to get the Class object cl proxy class (this is how the proxy class generated Leaving aside only need to know to use a class loader is the proxy class, and a reflecting interface implemented. deeply with down codes need to be generated with the ProxyGenerator.generateProxyClass proxy class, here only the code analysis) constructor getConstructor reacquisition by proxy class cl class object, reflected by the last constructor Getting a proxy class object, you can see the object with newInstance generate proxy classes when we passed the proxyHandler object h

It is worth mentioning that this proxy object is subject to reference interface class, this object is actually not part of realSubject and proxyHandler, but because it implements the subject interface, so you can convert it to a safe type of reference to the subject. But in fact we run this code, output s.getClass () is

 

 

 

 

 

That it does not belong to any class we've seen, but it belongs to the parent class is the proxy class

 

Finally, we summarize the steps to achieve the dynamic agent:

  1. InvocationHandler by implementing the interface to create your own call processor;

  2. to create a dynamic proxy class by specifying a set of interface objects and ClassLoader as Proxy class;

  3. The dynamic proxy class constructor is obtained by reflection, which is the only parameter type is a call processor interface type;

  4. Create instance via dynamic proxy class constructor object configured to call the handler is passed as a parameter.

 

Guess you like

Origin www.cnblogs.com/escape-w/p/11671667.html