Introduced
As we all know, AOP (facet-oriented programming) is one of the features of the spring framework. AOP provides extremely high scalability by setting crosscutting concerns (cross cutting concerns). So how does AOP work in spring? When you can only use core Java, but you need AOP technology, the answer to this question becomes extremely critical. Not only that, but in interviews with senior technical posts, such problems often appear as questions. No, my friend had recently been interviewed and was asked the tricky question of how to implement AOP without using spring and related libraries, only with core Java. So I'm going to provide an outline in this article to help you understand how to implement only one AOP with Core Java (of course, this AOP has some limitations in functionality). Note that this article is not a comparative study of Spring AOP and Java AOP, but rather a tutorial on implementing AOP in core Java with inherent design patterns.
Presumably readers already know what AOP is and how to use it in the spring framework, so this article focuses on how to implement AOP without spring. First, we need to know that spring is the implementation of AOP using JDK Proxy and cglib two technologies. JDK Dynamic Proxy provides a flexible way to hook up a method and perform a specified operation, but there is a constraint when performing an operation: You must first provide an associated interface and an implementation class for that interface. Practice the truth, let us through a case to understand this sentence! Now there is a calculator program that completes some mathematical operations. Let's consider the next division feature, where the question is: if the core framework already has a code to implement division, can we hijack (highjack) it and perform additional validation while the code is executing? The answer is yes, I will use the code snippet provided below to prove this. First look at the code for the underlying interface:
Public interface Calculator {public
int calculate (int a, int b);
}
The interface implements the code for the class as follows:
public class Calculatorimpl implements Calculator {
@Override public
int calculate (int a, int b) {return a/a
;
}
}
If we can not repair the above code, and can not make any changes to the core library, how to achieve the perfect verification function? Let's try the JDK dynamic proxy function.
public class Somehandler implements Invocationhandler {
//Code omitted for simplicity
..... @Override Public
Object Invoke (Object Proxy, Method method, object[] params) throws Throwable {
//Your complex Business validation and logic
Object result = Method.invoke (targetobject, params);
return result;
}
Let's test the class to see how it works with the checksum implemented by JDK dynamic Proxy.
public static void Main (string[] args) {
Calculatorimpl Calcimpl = new Calculatorimpl ();
Calculator proxied = (Calculator) proxyfactory.getproxy (Calculator.class, Calcimpl,
new Somehandler (Calcimpl));
int result = Proxied.calculate (a);
System.out.println ("FInal Result:::" + result);
}
From the result can be seen, simple to achieve a powerful Invocationhandler interface, we can get a hooking implementation. As described in the JDK documentation, the Invocationhandler interface handles a method invocation with the help of a proxy instance (proxy instance).
Now we know that Invocationhandler's Invoke () method can help us solve the problem. So, to solve a new problem-how do you do it before and after the method is executed? To be more specific, can we hook a method by adding multiple AOP (before, after, around) (add multiple aops, but I think handler is the role of aspect)? The answer is also yes. Follow these steps to create a streamlined code template that meets this need:
- Create an abstract class to apply AOP to the target object.
- Create two AOP named Beforehandler and Afterhandler. The former works before the method executes, and the latter works after the method execution ends.
- Creates a proxy class that allows all AOP handler and target objects to be passed in as parameters, creating a hook.
- Add your own business logic or crosscutting concerns.
- Finally, the proxy object is created by passing in the relevant parameters.
Two ways to implement AOP:
Dynamic proxy implementation provided by 1,JDK
interface
Public interface UserBean
{
void GetUser ();
void AddUser ();
void UpdateUser ();
void DeleteUser ();
}
Original Implementation Class
public class Userbeanimpl implements UserBean
{
private String user = null;
Public Userbeanimpl ()
{
} public
Userbeanimpl (String user)
{
this.user = user
}
Public String GetUserName ()
{return
user;
}
public void GetUser ()
{
System.out.println (' This is GetUser () method! ');
}
public void SetUser (String user)
{
this.user = user;
System.out.println ("This is SetUser () method!");
}
public void AddUser ()
{
System.out.println (' This is AddUser () method! ');
}
public void UpdateUser ()
{
System.out.println (' This is UpdateUser () method! ');
}
public void DeleteUser ()
{
System.out.println (' This is deleteuser () method! ');
}
proxy class
Import Java.lang.reflect.InvocationHandler;
Import Java.lang.reflect.Method;
Import Java.lang.reflect.Proxy;
Import Com.cignacmc.finance.bean.UserBeanImpl;
public class Userbeanproxy implements Invocationhandler
{
private Object targetobject;
Public Userbeanproxy (Object targetobject)
{
this.targetobject = targetobject;
}
public object invoke (object proxy, Method method, object[] args) throws Throwable
{
Userbeanimpl = Rbeanimpl) TargetObject;
String userName = Userbean.getusername ();
Object result = null;
Permission to determine
if (userName!= null &&! "". Equals (UserName))
{result
= Method.invoke (TargetObject, args);
}
return result;
}
Test class
Import Java.lang.reflect.Proxy;
Import Com.cignacmc.finance.bean.UserBean;
Import Com.cignacmc.finance.bean.UserBeanImpl;
Import Com.cignacmc.finance.proxy.UserBeanProxy;
public class Proxyexe {public static void main (string[] args) {System.out.println ("proved ... ...");
Userbeanimpl targetobject = new Userbeanimpl ("Bob Liang");
Userbeanproxy proxy = new Userbeanproxy (targetobject); Build Agent Object UserBean object = (UserBean) proxy.newproxyinstance (Targetobject.getclass (). getClassLoader (), t
Argetobject.getclass (). Getinterfaces (), proxy);
Object.adduser ();
System.out.println ("NO proved ... ..."); ".
TargetObject = new Userbeanimpl ();
Proxy = new Userbeanproxy (targetobject); Build Agent object = (UserBean) proxy.newproxyinstance (Targetobject.getclass (). getClassLoader (), Targetobje
Ct.getclass (). Getinterfaces (), proxy);
Object.adduser ();
}
}
Output:
proved ........ This is AddUser () method!
NO proved .......
From the above example, we can successfully intercept the called Method AddUser () and handle it accordingly.
2, create proxy class through Cglib
The benefit is not to require our target object to implement the interface
Original class
public class Clientbean
{
private String name = NULL;
Public Clientbean ()
{
} public
Clientbean (String name)
{
this.name = name;
}
public void Addclient ()
{
System.out.println (' This is addclient () method! ');
}
public void Deleteclient ()
{
System.out.println (' This is deleteclient () method! ');
}
public void Getclient ()
{
System.out.println (' This is getclient () method! ');
}
public void Updateclient ()
{
System.out.println (' This is updateclient () method! ');
}
Public String getclientname ()
{return
name;
}
public void Setclientname (String name)
{
this.name = name;
}
}
proxy class
Import Java.lang.reflect.Method;
Import Com.cignacmc.finance.bean.ClientBean;
Import Net.sf.cglib.proxy.Enhancer;
Import Net.sf.cglib.proxy.MethodInterceptor;
Import Net.sf.cglib.proxy.MethodProxy;
public class Cglibproxy implements Methodinterceptor {private Object targetobject;
public Object Createproxyobject (object targetobject) {this.targetobject = TargetObject;
Enhancer enhancer = new enhancer ();
Enhancer.setsuperclass (This.targetObject.getClass ());
Enhancer.setcallback (this);
return Enhancer.create ();
public object Intercept (object proxy, Method method, object[] args, Methodproxy methodproxy) throws Throwable
{Clientbean Clientbean = (Clientbean) targetobject;
String userName = Clientbean.getclientname ();
Object result = null; if (userName!= null &&! "".
Equals (UserName)) {result = Method.invoke (TargetObject, args);
return result;
}
}
Test class
Import Java.lang.reflect.Proxy;
Import Com.cignacmc.finance.bean.ClientBean;
Import Com.cignacmc.finance.bean.UserBean;
Import Com.cignacmc.finance.bean.UserBeanImpl;
Import Com.cignacmc.finance.proxy.CGLibProxy;
Import Com.cignacmc.finance.proxy.UserBeanProxy;
public class Proxyexe
{public
static void Main (string[] args)
{
System.out.println ("...). Cglib Proxy ...
............ System.out.println ("proved .... ...)";;
...... Cglibproxy cproxy = new Cglibproxy ();
Clientbean Clientbean = (Clientbean) cproxy.createproxyobject (New Clientbean ("Bob Liang"));
Clientbean.addclient ();
System.out.println ("NO proved ... ...)
", and the "NO" is not. Cproxy = new Cglibproxy ();
Clientbean = (Clientbean) cproxy.createproxyobject (New Clientbean ());
Clientbean.addclient ();
}
Output:
............. Cglib Proxy ...
..........
proved ............. This is addclient () method!