Agent mode -- dynamic agent
Static proxy: the proxy class must exist,
Dynamic agent: when the program is running, the agent class is dynamically generated according to the object to be represented.
Type: 1. Dynamic agent based on JDK
2. Dynamic agent based on CGLIB
1 dynamic agent based on JDK
Static, directly using Proxy call
newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
ClassLoader: class loader, because of the dynamic proxy class, with the help of others' class loader. Generally, the proxy object is used
Class loader.
Class[] interfaces: the collection of interface class objects, the proxy for the interface, and which interface is used as the proxy. It is generally used
Is the interface of the proxy object.
InvocationHandler: handle, callback function, write the rule code of the agent
public Object invoke(Object arg0, Method arg1, Object[] arg2)
Object arg0: proxy object
Method arg1: proxy method
Object[] arg2: array of parameters when the proxy method is executed
public class MyJDKProxy { public static void main(String[] args) { //Target object -- proxied object TeamService teamService=new TeamService(); //Return proxy object //Call the static method newProxyInstance in the Proxy class in the JDK to get the instance of the dynamic Proxy class IService proxyService= (IService) Proxy.newProxyInstance( teamService.getClass().getClassLoader(), teamService.getClass().getInterfaces(), new InvocationHandler() { //Write proxy rules for callback functions @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { System.out.println("Start transaction"); //core business Object invoke = method.invoke(teamService, args); System.out.println("Commit transaction"); return invoke; }catch (Exception e){ System.out.println("Rollback transaction"); e.printStackTrace(); throw e; }finally { System.out.println("finally---------"); } } } ); //Proxy object proxyService.add(); System.out.println(teamService.getClass()); System.out.println(proxyService.getClass()+"--------"); } }
2 structured design
Mode 1:
public class ProxyHandler implements InvocationHandler { private IService service;//Target object private AOP aop;//section public ProxyHandler(IService service, AOP aop) { this.service = service; this.aop = aop; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { aop.before(); Object invoke = method.invoke(service, args);//core business aop.after(); return invoke; }catch (Exception e){ aop.exception(); e.printStackTrace(); throw e; }finally { aop.myFinally(); } } }
public static void main2(String[] args) { //Target object -- proxied object TeamService teamService=new TeamService(); //section AOP tranAop=new TranAOP(); //Return proxy object JDK based dynamic proxy IService proxyService= (IService) Proxy.newProxyInstance( teamService.getClass().getClassLoader(), teamService.getClass().getInterfaces(), new ProxyHandler(teamService,tranAop) ); //Proxy object proxyService.add(); System.out.println(teamService.getClass() System.out.println(proxyService.getClass()+"------"); }
Mode 2:
public class ProxyFactory { private IService service;//Target object private AOP aop;//section public ProxyFactory(IService service, AOP aop) { this.service = service; this.aop = aop; } /** * Get an example of a dynamic proxy * @return */ public Object getProxyInstance() { return Proxy.newProxyInstance( service.getClass().getClassLoader(), service.getClass().getInterfaces(), new InvocationHandler() { //Write proxy rules for callback functions @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { aop.before(); //core business Object invoke = method.invoke(service, args); aop.after(); return invoke; }catch (Exception e){ aop.exception(); e.printStackTrace(); throw e; }finally { aop.myFinally(); } } } ); } }
public static void main(String[] args) { //Target object -- proxied object TeamService teamService=new TeamService(); //section AOP tranAop=new TranAOP(); AOP logAop=new LogAop(); //Get proxy object IService service= (IService) new ProxyFactory(teamService,tranAop).getProxyInstance(); IService service1= (IService) new ProxyFactory(service,logAop).getProxyInstance(); //Secondary agent service1.add(); //The core business + service code is a complete business method mixed together }
The proxy object does not need to implement the interface, but the target object must implement the interface; Otherwise, you cannot use JDK dynamic proxy. If you want to extend the function,
But the target object does not implement the interface. How to extend the function?
Subclass to implement the proxy CGLIB.
3 dynamic agent based on CGLIB
Cglib proxy, also known as subclass proxy. Build a subclass object in memory to expand the function of the target object.
One limitation of dynamic proxy in JDK is that objects using dynamic proxy must implement one or more interfaces. If you want to proxy a class that does not implement an interface, you can use CGLIB implementation.
CGLIB is a powerful high-performance code generation package, which can extend Java classes and implement Java interfaces at run time. It is widely used by many AOP frameworks, such as Spring AOP and dynaop, to provide them with method interception.
The bottom layer of CGLIB package is to convert bytecode and generate new classes by using a small and fast bytecode processing framework ASM. Direct use of ASM is discouraged because it requires you to be familiar with the internal structure of the JVM, including the format of class files and instruction sets.
3.1 testing
public class NBAService { public int add(String name,int id){ System.out.println("NBAService---- add----"); return id; } }
public static void main(String[] args) { //Target object: no interface NBAService nbaService=new NBAService(); //Create proxy object: select cglib dynamic proxy NBAService proxyService= (NBAService) Enhancer.create( nbaService.getClass(), new MethodInterceptor() { //Write proxy rules for callback functions @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { try { System.out.println("Start transaction"); //core Object invoke = methodProxy.invokeSuper(o, objects); System.out.println("Commit transaction"); return invoke; }catch (Exception e){ System.out.println("Transaction rollback"); throw e; }finally { System.out.println("finally------------"); } } } ); //Proxy object int res=proxyService.add("huren",1001); System.out.println(res); }
3.2 structured design method
public class CglibProxyFactory { //Target object private NBAService nbaService;//No interface implemented //section private AOP aop; /** * Create proxy object * @param nbaService * @param aop * @return */ public Object getProxyInstance(NBAService nbaService,AOP aop){ return Enhancer.create(nbaService.getClass(), new MethodInterceptor() { //Write proxy rules for callback functions @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { try { aop.before(); Object o1 = methodProxy.invokeSuper(o, objects); aop.after(); return o1; }catch (Exception e){ aop.exception(); throw e; } finally { System.out.println("finally-----------"); } } } ); } }
public static void main(String[] args) { //Target object: no interface NBAService nbaService=new NBAService(); //Create slice AOP tranAop=new TranAOP(); //Create proxy object: select cglib dynamic proxy NBAService proxyInstance = (NBAService) new CglibProxyFactory().getProxyInstance(nbaService, tranAop); int res=proxyInstance.add("huren",1001); System.out.println(res); }