[Design Pattern] Verhaltensmuster: Interceptor


Thomas Darimont

Premium-User
Hallo,

dieser Beitrag erklärt das Verhaltensmuster: Interceptor

Java:
package de.tutorials.design.patterns.behavioral;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class InterceptorExample {
	public static void main(String[] args) {
		Dispatcher dispatcher = new DispatcherImpl(new TracingInterceptor(), new SecurityInterceptor());

		Service service = dispatcher.newProxy(Service.class, new ServiceImpl());

		System.out.println("Result: " + service.businessMethod("foo"));
	}

	
	static interface Service {
		String businessMethod(String arg);
	}

	static class ServiceImpl implements Service {
		@Override
		public String businessMethod(String arg) {
			System.out.println("Code execution");
			return "#" + arg + "#";
		}
	}

	static interface Interceptor {
		Object intercept(MethodInvocation mi);
	}

	static class TracingInterceptor implements Interceptor {
		@Override
		public Object intercept(MethodInvocation mi) {
			System.out.println("TRACE Before: " + mi.getMethod());
			try {
				return mi.proceed();
			} finally {
				System.out.println("TRACE After: " + mi.getMethod());
			}
		}
	}

	static class SecurityInterceptor implements Interceptor {
		@Override
		public Object intercept(MethodInvocation mi) {
			System.out.println("SECURITY Before " + mi.getMethod());
			try {
				return mi.proceed();
			} finally {
				System.out.println("SECURITY After " + mi.getMethod());
			}
		}
	}

	
	static interface Dispatcher {
		<INF, IMPL extends INF> INF newProxy(Class<INF> infType, IMPL impl);
	}

	static class DispatcherImpl implements Dispatcher {
		
		private final static Method interceptMethod;
		
		static{
			try {
				interceptMethod = Interceptor.class.getDeclaredMethod("intercept", MethodInvocation.class);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		
		private final Interceptor[] interceptors;

		public DispatcherImpl(Interceptor... interceptors) {
			this.interceptors = interceptors;
		}

		public <INF, IMPL extends INF> INF newProxy(Class<INF> infType, IMPL impl) {
			return infType.cast(Proxy.newProxyInstance(infType.getClassLoader(), new Class[] { infType }, createInterceptorHandler(impl)));
		}

		private InvocationHandler createInterceptorHandler(final Object target) {
			return new InvocationHandler() {
				@Override
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					MethodInvocation mi = wrapInterceptorsAround(new MethodInvocation(target, method, args));
					return mi.proceed();
				}
			};
		}

		private MethodInvocation wrapInterceptorsAround(MethodInvocation mi) {
			MethodInvocation currentMethodInvocation = mi;
			for (int i = interceptors.length - 1; i >= 0; i--) {
				currentMethodInvocation = new MethodInvocation(interceptors[i],interceptMethod,new Object[] { currentMethodInvocation });
			}
			return currentMethodInvocation;
		}
	}


	static class MethodInvocation {

		private final Object target;
		private final Method method;
		private final Object[] args;

		private Object result;

		public MethodInvocation(Object target, Method method, Object[] args) {
			this.target = target;
			this.method = method;
			this.args = args;
		}

		public Object proceed() {
			try {
				return method.invoke(target, args);
			} catch (Throwable e) {
				throw new RuntimeException(e);
			}
		}

		public Object getResult() {
			return result;
		}

		public void setResult(Object result) {
			this.result = result;
		}

		public Object getTarget() {
			return target;
		}

		public Method getMethod() {
			return method;
		}

		public Object[] getArgs() {
			return args;
		}
	}
}
Ausgabe:
Code:
TRACE Before: public abstract java.lang.Object de.tutorials.design.patterns.behavioral.InterceptorExample$Interceptor.intercept(de.tutorials.design.patterns.behavioral.InterceptorExample$MethodInvocation)
SECURITY Before public abstract java.lang.String de.tutorials.design.patterns.behavioral.InterceptorExample$Service.businessMethod(java.lang.String)
Code execution
SECURITY After public abstract java.lang.String de.tutorials.design.patterns.behavioral.InterceptorExample$Service.businessMethod(java.lang.String)
TRACE After: public abstract java.lang.Object de.tutorials.design.patterns.behavioral.InterceptorExample$Interceptor.intercept(de.tutorials.design.patterns.behavioral.InterceptorExample$MethodInvocation)
Result: #foo#
Gruß Tom