JAVA implements simple AOP framework functions
Preface
You are welcome to repost original articles. Please retain the source. If you have any questions or suggestions, please feel free to reply. Email: Maxwell_nc@163.com
Write a factory class BeanFactory to create the config file. the instance object of the target class or proxy class specified in properties. The getBean method in the class returns an Instance Object Based on the string passed in by the parameter, if the class name is the ProxyFactoryBean class, the Instance Object of the proxy class is created. Otherwise, the instance object is created and returned by calling the constructor without parameters of the target class, which is similar to the Spring framework's AOP function.
BeanFactory Class Analysis and code
This class passes in an input stream receiving configuration file through the constructor. Another main method, getBean, is the core of the entire framework. This method first obtains the name of the class to be created in the configuration file, and then calls the constructor without parameters to create an instance object (the class to be created in the configuration must be a JavaBean, otherwise, there may not be any constructor without parameters). The instance object is used to determine whether it is a ProxyFactoryBean object. If yes, it is converted to a ProxyFactoryBean object and the method getProxy in the ProxyFactoryBean class is called to create a proxy.
Package maxwell_nc.aopframework; import java. io. IOException; import java. io. inputStream; import java. util. properties; public class BeanFactory {Properties props = new Properties (); public BeanFactory (InputStream ips) {try {props. load (ips); // read the configuration file} catch (IOException e) {e. printStackTrace () ;}} public Object getBean (String key) {// The purpose of this method is to obtain the class Object referred to by a key. // if this class is of the ProxyFactoryBean class, that is, the proxy class is used to create a proxy object and return // If not, the String clazzname = props is returned by directly calling a constructor without parameters to create an object. getProperty (key); Object bean = null; try {Class clazz = Class. forName (clazzname); bean = clazz. newInstance (); // For javabean, there must be a constructor without parameters} catch (Exception e) {e. printStackTrace ();} if (bean instanceof ProxyFactoryBean) {// converts it to a ProxyFactoryBean Object. It is convenient to use the getProxy method and the set Method ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean; try {// get the desired Object target and the Advice Class Object target = Class. forName (props. getProperty (key + ". target ")). newInstance (); Advice ad = (Advice) Class. forName (props. getProperty (key + ". advice ")). newInstance (); proxyFactoryBean. setTarget (target); proxyFactoryBean. setAd (ad); proxy = proxyFactoryBean. getProxy ();} catch (Exception ex) {ex. printStackTrace ();} return proxy;} return bean ;}}
ProxyFactoryBean Class Analysis and code
The core is that getProxy uses the static method newProxyInstance of the Proxy class to create a Proxy object, overwrite the invoke method, and call it using the InvocationHandler processing method. The Advice implementation class is inserted in the middle of the invoke method.
Package maxwell_nc.aopframework; import java. lang. reflect. invocationHandler; import java. lang. reflect. proxy; import java. lang. reflect. method; public class ProxyFactoryBean {private Object target; private Advice ad; public Object getProxy () {// use the static Method of the Proxy class newProxyInstance to create the Proxy Object proxyobj = Proxy. newProxyInstance (target. getClass (). getClassLoader (), target. getClass (). getInterfaces (), new InvocationHandler () {public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {ad. beforeMethod (method); Object obj = method. invoke (target, args); ad. afterMethod (method); return obj ;}}); return proxyobj ;}public Object getTarget () {return target ;}public void setTarget (Object target) {this.tar get = target ;} public Advice getAd () {return ad;} public void setAd (Advice ad) {this. ad = ad ;}}
Advice interface and implementation class
This does not need to be parsed. You can directly send the code to the Advice interface.
package maxwell_nc.aopframework;import java.lang.reflect.Method;public interface Advice { void beforeMethod(Method method); void afterMethod(Method method);}
Advice implementation class
package maxwell_nc.aopframework;import java.lang.reflect.Method;public class MyAdvice implements Advice { @Override public void afterMethod(Method method) { System.out.println(method.getName()+"_start"); } @Override public void beforeMethod(Method method) { System.out.println(method.getName()+"_end"); }}
Test class and configuration file
Here we use a separate class for testing. We will first write a config. properties file.
#bean=java.util.ArrayListbean=maxwell_nc.aopframework.ProxyFactoryBeanbean.target=java.util.ArrayListbean.advice=maxwell_nc.aopframework.MyAdvice
Note: If you use the first line, you will use a normal bean, and the second line will create a ProxyFactoryBean. You can annotate them separately for testing. Below is the test class
Package maxwell_nc.aopframework; import java. io. inputStream; import java. util. collection; public class AopFrameworkTest {public static void main (String [] args) {InputStream ips = AopFrameworkTest. class. getResourceAsStream ("config. properties "); // create the factory BeanFactory beanFactory = new BeanFactory (ips); // obtain the Object and print the corresponding bytecode name Object bean = beanFactory. getBean ("bean"); System. out. println (bean. getClass (). getName (); // The following statement can test whether the Advice class is valid // (Collection) bean ). clear ();}}
We will try to create a proxy object and test the result in Myeclipse: the proxy object is obtained normally and the Advice class function is called.
Summary
In fact, you can also define ProxyFactoryBean as an interface. There are many bean classes that implement this interface. Each bean class has its own getProxy method, which is more flexible.