I have been in JAVA pit for more than July, and I also try to build a framework by myself. Recently, I am fascinated by this aspect of spring aop, so I record my current small demo, and I will continue to improve my demo later. I hope that the great gods will not be stingy to teach me.
It mainly uses reflection and java's own proxy class. Theoretical knowledge will not be said, because I am not very clear at present, to avoid misleading, or to avoid talking about it. OK, just follow the code.
Structure:
Interface
Person.java
public interface Person { void say(); }
Interface implementation class
Man.java
public class Man implements Person { @Override public void say() { System.out.println("Man say:...."); } }
Custom annotation
@interface WaterAOP
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.METHOD}) @Documented public @interface WaterAOP { enum METHOD{before,after,afterthrowing} METHOD method() default METHOD.after; String Name() default "Class full name"; }
Custom annotation class
WaterLog.java
public class WaterLog { @WaterAOP(Name = "com.water.aop.attempt3.Man",method = WaterAOP.METHOD.after) public void afterAction(){ System.out.println("Postposition behavior"); } @WaterAOP(Name = "com.water.aop.attempt3.Man",method = WaterAOP.METHOD.before) public void beforeAction(){ System.out.println("Preposition behavior"); } }
Implement the custom proxy class
The third parameter of the Proxy.newProxyInstance() method does the trick. The lambda expression of java8 is used.
)
ProxyFactory.java
public class ProxyFactory { // Maintain a proxy object that implements the interface,Change to object group after,From the shallower to the deeper private Person person; private WaterLog waterLog; private Method beforeMethod=null,afterMethod=null; public ProxyFactory(Person person,WaterLog waterLog){ this.person=person; this.waterLog=waterLog; } public Object getProxyInstance(){ return Proxy.newProxyInstance( person.getClass().getClassLoader(), person.getClass().getInterfaces(), // The first parameter is the agent. You can use this parameter if you want to do something to the agent; // The second is the method to be implemented, // The third is the parameters required to execute the method. (Object proxyObj, Method method,Object[] args)->{ //If no incoming aop Directly return to null if(waterLog==null){ return null; } Class aop=waterLog.getClass(); Class c = person.getClass(); // Obtain aop Class and assign to some custom variables. The following determines whether there is annotation based on whether these variables have values getAnnotation(aop,c); if(beforeMethod!=null){ beforeMethod.invoke(waterLog); } // The proxy object executes the method and gets the return value Object returnValue=method.invoke(person,args); if(afterMethod!=null){ afterMethod.invoke(waterLog); } return returnValue; } ); } private void getAnnotation(Class aop,Class proxy){ //If there is AOP Class if(waterLog!=null){ // Get all methods of tangent class Method[] methodsAOP=aop.getMethods(); // If the method of the log class to be cut in is not empty if(methodsAOP!=null){ for(Method logMethod:methodsAOP){ // Obtain WaterLog Class method WaterAOP annotation WaterAOP waterAOP=logMethod.getAnnotation(WaterAOP.class); if(waterAOP!=null) { // If AOP The annotation on is the same as the class name passed in if (proxy.toString().substring(6).equals(waterAOP.Name())) { if (waterAOP.method() == WaterAOP.METHOD.before) { // assignment ,Later beforeMethod=logMethod; }else if(waterAOP.method() == WaterAOP.METHOD.after){ afterMethod=logMethod; } } } } } } } }
Test class
Test.java (junit is a test package, or you can use the main method directly)
public class Test { @org.junit.Test public void waterAOP(){ Person person=new Man(); Person proxyPerson=(Person) new ProxyFactory(person,new WaterLog()).getProxyInstance(); proxyPerson.say(); } }
The general process is: pass in the class to be represented and the user-defined annotation class, use reflection to obtain the annotation attribute value of the method in the annotation class, then compare, and then carry out the corresponding operation.