java - Bind byte buddy method delegation only to methods with annotated parameters -
i want decorate existing objects method calls automatically validated. managed delegate method call interceptor calls hibernate validator , far works fine:
public class hibernatebeanvalidator implements beanvalidator{ validatorfactory factory = validation.builddefaultvalidatorfactory(); @override public <t> t addmethodvalidation(t object) { executablevalidator executablevalidator = factory.getvalidator().forexecutables(); class<? extends t> dynamictype = (class<? extends t>)new bytebuddy() .subclass(object.getclass()) .method(ispublic()).intercept(methoddelegation.to(new validationinterceptor(object, executablevalidator)).andthen(supermethodcall.instance)) .make() .load(getclass().getclassloader(), classloadingstrategy.default.wrapper) .getloaded(); try { t validatedobject = dynamictype.newinstance(); return validatedobject; } catch (instantiationexception | illegalaccessexception e) { throw new runtimeexception(e); } } public static class validationinterceptor { private final object validatedobject; private final executablevalidator executablevalidator; public <t> validationinterceptor(t object, executablevalidator executablevalidator) { this.validatedobject = object; this.executablevalidator = executablevalidator; } public void validate(@origin method method, @allarguments object[] arguments) throws exception { set<constraintviolation<object>> constraintviolations = executablevalidator.validateparameters(validatedobject, method, arguments); if(! constraintviolations.isempty()) { throw new validationexception(constraintviolations); } } } }
what improve bind method calls methods have @ least 1 parameter annotated constraint annotation, such as:
class echo { public string repeat(@notnull string word) { /* should bind validation here */ return word; } public string notannotated(string word) { /* should not bind validation */ return word; } }
how specify elementmatcher in byte buddy bind methods parameters annotated annotations annotated @constraint, such @notnull (taken javax.validation.constraints):
@target({ method, field, annotation_type, constructor, parameter }) @retention(runtime) @documented @constraint(validatedby = { }) public @interface notnull { string message() default "{javax.validation.constraints.notnull.message}"; class<?>[] groups() default { }; class<? extends payload>[] payload() default { }; /** * defines several {@link notnull} annotations on same element. * * @see javax.validation.constraints.notnull */ @target({ method, field, annotation_type, constructor, parameter }) @retention(runtime) @documented @interface list { notnull[] value(); } }
your problem can solved implementing custom elementmatcher
used identify methods intercepted. currently, using predefined ispublic()
interceptor not consider annotations public
modifier of method. predefined annotations can chained, can build suitable matcher follows:
ispublic().and(hasparameter(hasannotation(namestartswith("javax."))))
of course, can implement own matchers without using predfined ones.
Comments
Post a Comment