Outline
- proxy
- proxy
- cglib
- summary
First, agents
Why use a proxy? In fact, it is hoped, without modifying objects, enhanced object.
Static Agent:
- Static proxy mode, the proxy class and target class implements the same interface method, the proxy class target class method calls, method calls before and after implementation requires enhanced logic.
- One problem is that the static agent, each agent class and target class, correspondence, multi-class situation requires the agent, the agent requires a lot of class, it is difficult to maintain.
Dynamic Agent:
- Dynamic Agent is dynamically generated runtime classes, not at compile time.
- Dynamic Agent There are two different ways, one is the lower cladding of the reflection jdk Prxoy, one is cglib.
Two, Proxy
Proxy proxy object needs to generate a target object implements at least one interface.
Proxy dynamic agent by reflection.
Generate a proxy object to call the Proxy newProxyInstance method.
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
classloader loader- target object
interfaces- target object implements the interface
InvocationHandler- processor, when the interface method of the target object is called a processor invoke method is called in order to achieve dynamic proxy
Look at InvocationHandler
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
proxy- proxy object
method is invoked method-
args- parameters passed when calling the method
invoke the proxy method returns a value of the return value
test:
interface:
public interface Speak { String say(String content); }
Target class:
import lombok.Data;
@Data public class Person implements Speak{ private String name; private int age; public String say(String content){ System.out.println("hi"+name+age+"content:"+content); return "say return"; } }
Acting factory:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class the ProxyFactory { // maintain a target object Private Object target; public the ProxyFactory (Object target) { the this .target = target; } // generates a proxy object public Object getProxyInstance () { return the Proxy.newProxyInstance ( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println ( "before Method:" + method.getName ()); // execution of the target object method, return return value. The returnValue = Object Method.invoke (target, args); System.out.println("end method:"+method.getName()); return returnValue; } }); } }
Proxy object the proxy method calls before and after playing a line of words.
public static void main(String[] args) { Person p = new Person(); p.setAge(11); p.setName("xx"); ProxyFactory factory = new ProxyFactory(p); Object proxyInstance = factory.getProxyInstance(); Speak speak = (Speak) proxyInstance; String returnValue = speak.say("haha"); System.out.println("returnValue:"+returnValue); }
Three, cglib
Static agents and must implement the interface, but without this restriction cglib, cglib dynamically generated by the subclass bytecode manipulation, so final target class can not be modified.
Similar to the proxy we also need to rewrite a processor
public interface MethodInterceptor extends Callback { Object (Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable; }
proxy- proxy object
method is invoked method-
methodProxy- proxy method (specifically I is not particularly clear)
Intercept proxy method returns a value of the return value
test:
Person does not need to rewrite the implementation of the interface
import lombok.Data; @Data public class Person{ private String name; private int age; public String say(String content){ System.out.println("hi"+name+age+"content:"+content); return "say return"; } }
Acting factory:
import org.assertj.core.internal.cglib.proxy.Enhancer; import org.assertj.core.internal.cglib.proxy.MethodInterceptor; import org.assertj.core.internal.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CgProxyFactory <T> { // maintenance target object Private T target; public CgProxyFactory (T target) { the this .target = target; } // obtain the proxy public T getProxyInstance () { Enhancer and = new Enhancer (); en.setSuperclass ( the this .target.getClass ()); // set interceptor en.setCallback ( new new MethodInterceptor () { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("before method:"+method.getName()); Object returnValue = method.invoke(target, objects); System.out.println("end method:"+method.getName()); return returnValue; } }); return (T) en.create(); } }
And before the proxy objects, hit a line of words before and after the proxy method call.
public static void main(String[] args) { Person p = new Person(); p.setAge(11); p.setName("xx"); CgProxyFactory<Person> factory = new CgProxyFactory(p); Person proxyInstance = factory.getProxyInstance(); String returnValue = proxyInstance.say("cg"); System.out.println("returnValue:" + returnValue); }
IV Summary:
- Proxy proxy class need to implement the interface, the underlying reflective.
- Cglib final proxy object can not be modified, underlying bytecode operation.
- The spring will be the case whether the target class implements the interface, the dynamic proxy mode switching may be used to force cglib configure.