Write yourself a Web framework (ii): Implement AOP_AOP

Source: Internet
Author: User
Tags aop throwable

Series of articles:

Write yourself a web framework (i): implementation of the IOC and MVC

First, the basic introduction
Implementation function: When all the methods in controller are invoked, it takes a long time to compute the call. Basic Technology: Dynamic agent
Second, the realization of ideas since to proxy all controller class, then use the annotation to distinguish whether it is controller. Define a aspect Annotation:

@Target (Elementtype.type)
@Retention (retentionpolicy.runtime) public
@interface Aspect {

	//annotations
	class<? Extends annotation> value ();

}

A class can be multiple agents, such as both computational time and security verification, so we can use the idea of the agent chain to solve, define a following interface and the basic proxy implementation class:
Public interface Proxy {
	//execute chained Agent
	Object doproxy (Proxychain proxychain) throws Throwable;
}
public class Proxychain {private final class<?> targetclass;  Private Final object targetobject;//target object Private final method targetmethod;//target approach private final methodproxy methodproxy; 
	Agent method Private Final object[] methodparams; Private list<proxy> proxylist = new arraylist<proxy> ();

	Proxy object list private int proxyindex = 0; Public Proxychain (class<?> targetclass, Object TargetObject, Method Targetmethod, Methodproxy methodproxy, Object
		[] methodparams, list<proxy> proxylist) {super ();
		This.targetclass = Targetclass;
		This.targetobject = TargetObject;
		This.targetmethod = Targetmethod;
		This.methodproxy = Methodproxy;
		This.methodparams = Methodparams;
	This.proxylist = proxylist;
	Public class<?> Gettargetclass () {return targetclass;
	Public method Gettargetmethod () {return targetmethod;
	Object[] Getmethodparams () {return methodparams; The public Object Doproxychain () throws Throwable {Object MethodresUlt
		if (Proxyindex < Proxylist.size ()) {Methodresult = Proxylist.get (proxyindex++). Doproxy (this);
		else {Methodresult = Methodproxy.invokesuper (TargetObject, methodparams);
	return methodresult;
 }

public class Aspectproxy implements Proxy {private static final Logger Logger = Loggerfactory.getlogger (aspectproxy.clas

	s);
		Public final Object Doproxy (Proxychain proxychain) throws Throwable {object result = NULL;
		Class<?> cls = Proxychain.gettargetclass ();
		Method method = Proxychain.gettargetmethod ();
		object[] params = Proxychain.getmethodparams ();
		Begin ();
				try {if (Intercept (CLS, method, params)} {before (CLS, method, params);
				result = Proxychain.doproxychain ();
			After (CLS, method, params);
			else {result = Proxychain.doproxychain ();
			The catch (Exception e) {logger.error ("proxy fail", e);
			Error (CLS, method, params, E);
		Throw e;
		Finally {end ();
	return result; The public void Begin () {} is public Boolean intercept (Class<?> cls, method method, object[] params) throws Throwa
	ble {return true; public void before (Class<?> cls, method method, object[] params) throws Throwable {} public VoiD After (class<?> cls, method method, object[] params) throws Throwable {} public void error (class<?> cls, Method method, object[] params, throwable e) throws throwable {} public void End () {}}

The top two classes look together, see more than a few times can understand the whole process: Aspectproxy used in the template method, to standardize the operation of the entire agent order: first call before, and then judge whether the agent chain is the last agent, if not, continue the next agent operation, Then call after, if the last one, invoke the original proxy method with reflection, and then call after.

We can define such aspect in our own project (not the framework):
@Aspect (value=controller.class) Public
class Controlleraspect extends Aspectproxy {
	private static final Logger Logger = Loggerfactory.getlogger (controlleraspect.class);
	private long begin;

	@Override public
	Void before (Class<?> cls, method method, object[] params) throws Throwable {
		Logger.debug ("-----begin-----");
		Logger.debug (String.Format ("Class:%s", Cls.getname ());
		Logger.debug (String.Format ("Method:%s", Method.getname ());
		Begin = System.currenttimemillis ();
	}

	@Override public
	Void after (Class<?> cls, method method, object[] params) throws Throwable {
		Logger.debug (String.Format ("Time:%dms", System.currenttimemillis ()-begin);
		Logger.debug ("-----End-----");
	}

As for the job of creating an agent, we give it to Proxymanager:
/** *
 Code Manager
 * * 
 * @author Shen
 *
 /Public
class Proxymanager {

	@SuppressWarnings (" Unchecked ") public
	static <T> T createproxy (final class<?> targetclass, final list<proxy> Proxylist) {return
		(T) enhancer.create (Targetclass, New Methodinterceptor () {Public
			object intercept (object TargetObject, Method Targetmethod, object[] methodparams,
					methodproxy methodproxy) throws Throwable
				New Proxychain (Targetclass, TargetObject, Targetmethod, Methodproxy, Methodparams, Proxylist)
						. DoProxyChain ();
			}
		});
	}

}

The Cglib dynamic agent is used.
Then we just need to replace the corresponding class instance in the Beanhelper with the proxy object:
public class Aophelper {private static final Logger Logger = Loggerfactory.getlogger (Aophelper.class);
			static {try {map<class<?>, set<class<?>>> proxymap = Createproxymap ();
			Map<class<?&gt, list<proxy>> targetmap = Createtargetmap (Proxymap); for (MAP.ENTRY&LT;CLASS&LT;?&GT;, list<proxy>> TargetEntry:targetMap.entrySet ()) {class<?> Targetcla
				SS = Targetentry.getkey ();
				list<proxy> proxylist = Targetentry.getvalue ();
				Object proxy = Proxymanager.createproxy (Targetclass, proxylist);
			Beanhelper.setbean (Targetclass, proxy);
		The catch (Exception e) {logger.error ("AOP fail", e); }} private static Map<class<?>, Set<class<?>>> Createproxymap () throws Exception {MAP&LT;CL Ass<?&gt, set<class<?>>> proxymap = new Hashmap<class<?>, Set<class<?>>> (
		); set<class<?>> Proxyclassset = Classhelper.getclasssetbysuper(Aspectproxy.class);
			for (class<?> proxyclass:proxyclassset) {System.out.println (proxyclass);
				if (Proxyclass.isannotationpresent (Aspect.class)) {Aspect Aspect = proxyclass.getannotation (Aspect.class);
				System.out.println (Aspect.tostring ());
				set<class<?>> Targetclassset = createtargetclassset (aspect);
			Proxymap.put (Proxyclass, Targetclassset);
	} return Proxymap; private static set<class<?>> Createtargetclassset (Aspect Aspect) throws Exception {Set<class<?&gt
		;> targetclassset = new hashset<class<?>> (); class<?
		Extends annotation> Annotation = Aspect.value (); if (annotation!= null &&!annotation.equals (Aspect.class)) {Targetclassset.addall (
		Classhelper.getclasssetbyannotation (annotation));
	return targetclassset; private static Map<class<?>, list<proxy>> Createtargetmap (map<class<?>, Set<Class <?>>> Proxymap) throws Exception {map<class<?>, list<proxy>> targetmap = new Hashmap<class<?>, list<proxy>> (); for (MAP.ENTRY&LT;CLASS&LT;?&GT;, set<class<?>>> ProxyEntry:proxyMap.entrySet ()) {class<?> Pro
			Xyclass = Proxyentry.getkey ();
			set<class<?>> Targetclassset = Proxyentry.getvalue ();
				for (class<?> targetclass:targetclassset) {Proxy proxy = (proxy) proxyclass.newinstance ();
				if (Targetmap.containskey (Targetclass)) {Targetmap.get (Targetclass). Add (proxy);
					else {list<proxy> proxylist = new arraylist<proxy> ();
					Proxylist.add (proxy);
				Targetmap.put (Targetclass, proxylist);
	}} return targetmap;
 }

}


In this way, we complete the functions of AOP.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.