Ich stand heute vor dem Problem, dass ich mit einem AspectJ-Advice die Parameter von Methoden überprüfen wollte. Abhängig von dem Parametertyp sollte eine Exception geworfen werden. Meine Exceptions erben von einer Basisklasse, die in Abhängigkeit des Parametertyps weitere Exception-Codes enthalten. So kann z.B. die UserException neben dem Code NOT_FOUND (Parameter ist null) noch weitere Codes wie z.B. EMAIL_ALREADY_EXIST besitzen.

Meine Methoden sahen in etwa so aus:

public void methodeA(User _a, boolean _b);

public void methodeB(AnderesDomaenenObjekt _b, User _a);

public void methodeB(User _a, User _b);

Leider gibt es momentan noch keine Möglichkeit, einen entsprechenden Pointcut zu definieren, dem die Reihenfolge der Parameter egal ist.

Der Pointcut

	@Before(value = "execution (* de.mypackage.service..*.*(.., de.mypackage.domain.User, ..)) && args(*, _user, *")

funktioniert so nämlich nicht.
Um das Problem momentan zu umschiffen, muss man einen generischen Pointcut definieren, der die Parameter der Methode und die übergebenen Objekte überprüft.
Folgender Code überprüft alle übergebenen Parameter einer Methode und beachtet auch die angehängten Annotations an den jeweiligen Parameter.

@Aspect
@Component
public class ParameterValidAspect
{
	@SuppressWarnings("unchecked")
	@Before(value = "execution (* de.mypackage.service..*.*(..))")
	@Order(AspectOrder.FIRST)
	public void parameterNullCheck(JoinPoint pjp) throws SecurityException,
			NoSuchMethodException
	{
		MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
		String methodName = pjp.getStaticPart().getSignature().getName();
		Class<?>[] paramTypes = methodSignature.getParameterTypes();
		Annotation[][] annotationsByMethod = ((CodeSignature) pjp.getStaticPart()
				.getSignature()).getDeclaringType()
				.getMethod(methodName, paramTypes).getParameterAnnotations();
		Object[] methodArguments = pjp.getArgs();
		Object instance = null;

		for (int i = 0, m = paramTypes.length; i < m; i++)
		{
			instance = methodArguments[i];

			if (instance == null)
			{
				try
				{
					instance = paramTypes[i].newInstance();
				}
				catch (Exception e)
				{
				        // Instanzierungs-Exceptions handeln...
                                }
			}

			if (annotationsByMethod[i].length > 0)
				{
					for (Annotation annotation : annotationsByMethod[i])
					{
						// Annotation behandeln
					}
				}
			}

			if (methodArguments[i] == null)
			{
                                // ParameterNullException handelt dann den jeweiligen Objekttyp
				throw new ParameterNullException(instance);
			}
		}
	}
}

Noch ein allgemeiner Hinweise zur Benutzung von AspectJ in Zusammenhang mit dem Spring Framework: Werden Aspekte über die Annotation @Aspect beschrieben, muss der Aspekt auch mit @Component annotiert werden, damit sie per Auto-Discovery erkannt werden. Benutzt man @Component nicht, muss in der Spring-XML-Konfiguration der Aspekt instanziert werden!

I am asking you for a donation.

You liked the content or this article has helped and reduced the amount of time you have struggled with this issue? Please donate a few bucks so I can keep going with solving challenges.


0 Comments

Leave a Reply