Java Spring AOP之PointCut案例详解

网友投稿 254 2022-12-12

Java Spring AOP之PointCut案例详解

目录一、PointCut接口二、ClassFilter接口三、MethodMatcher接口总结

一、PointCut接口

/*

* Copyright 2002-2012 the original author or authors.

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* https://apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.springframework.aop;

/**

* Core Spring pointcut abstraction.

*

*

A pointcut is composed of a {@link ClassFilter} and a {@link MethodMatcher}.

* Both these basic terms and a Pointcut itself can be combined to build up combinations

* (e.g. through {@link org.springframework.aop.support.ComposablePointcut}).

*

* @author Rod Johnson

* @see ClassFilter

* @see MethodMatcher

* @see org.springframework.aop.support.Pointcuts

* @see org.springframework.aop.support.ClassFilters

* @see org.springframework.aop.support.MethodMatchers

*/

public interface Pointcut {

/**

* Return the ClassFilter for this pointcut.

* @return the ClassFilter (never {@code null})

*/

ClassFilter getClassFilter();

/**

* Return the MethodMatcher for this pointcut.

* @return the MethodMatcher (never {@code null})

*/

MethodMatcher getMethodMatcher();

/**

* Canonical Pointcut instance that always matches.

*/

Pointcut TRUE = TruePointcut.INSTANCE;

}

由源码可知,PointCut接口就是定义了两个元素,ClassFilter和MethodMatcher。PointCut接口就是为了获得这两个元素。换句话说,PointCut的功能,都包含在了这两个元素里。下面看这 两个元素源码。

二、ClassFilter接口

/*

* Copyright 2002-2019 the original author or authors.

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* https://apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.springframework.aop;

/**

* Filter that restricts matching of a pointcut or introduction to

* a given set of target classes.

*

*

Can be used as part of a {@link Pointcut} or for the entire

* targeting of an {@link IntroductionAdvisor}.

*

*

Concrete implementations of this interface typically should provide proper

* implementations of {@link Object#equals(Object)} and {@link Object#hashCode()}

* in order to allow the filter to be used in caching scenarios — for

* example, in proxies generated by CGLIB.

*

* @author Rod Johnson

* @see Pointcut

* @see MethodMatcher

*/

@FunctionalInterface

public interface ClassFilter {

/**

* Should the pointcut apply to the given interface or target class?

* @param clazz the candidate target class

* @return whether the advice should apply to the given target class

*/

boolean matches(Class> clazz);

/**

* Canonical instance of a ClassFilter that matches all classes.

*/

ClassFilter TRUE = TrueClassFilter.INSTANCE;

}

这个接口用来过滤要生成代理的类和给定的类是否匹配。

该接口的实现类应该提供正确的equals()方法和hashCode()方法,以便于能在缓存中使用。例如通过cglib生成的代理对象。(这句话什么意思,不理解)。

matches方法就是判断参数中的class类是否和切点定义的类相匹配。如果匹配,则生成代理对象,如果不匹配,则过滤掉。

三、MethodMatcher接口

/*

* Copyright 2002-2019 the original author or authors.

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* https://apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package org.springframework.aop;

import java.lang.reflect.Method;

/**

* Part of a {@link Pointcut}: Checks whether the target method is eligible for advice.

*

*

A MethodMatcher may be evaluated statically or at runtime http://(dynamically).

* Static matching involves method and (possibly) method attributes. Dynamic matching

* also makes arguments for a particular call available, and any effects of running

* previous advice applying to the joinpoint.

*

*

If an implementation returns {@code false} from its {@link #isRuntime()}

* method, evaluation can be performed statically, and the result will be the same

* for all invocations of this method, whatever their arguments. This means that

* if the {@link #isRuntime()} method returns {@code false}, the 3-arg

* {@link #matches(java.lang.reflect.Method, Class, Object[])} method will never be invoked.

*

*

If an implementation returns {@code true} from its 2-arg

* {@link #matches(java.lang.reflect.Method, Class)} method and its {@link #isRuntime()} method

* returns {@code true}, the 3-arg {@link #matches(java.lang.reflect.Method, Class, Object[])}

* method will be invoked immediately before each potential execution of the related advice,

* to decide whether the advice should run. All previous advice, such as earlier interceptors

* in an interceptor chain, will have run, so any state changes they have produced in

* parameters or ThreadLocal state will be available at the time of evaluation.

*

*

Concrete implementations of this interface typically should provide proper

* implementations of {@link Object#equals(Object)} and {@link Object#hashCode()}

* in order to allow the matcher to be used in caching scenarios — for

* example, in proxies generated by CGLIB.

*

* @author Rod Johnson

* @since 11.11.2003

* @see Pointcut

* @see ClassFilter

*/

public interface MethodMatcher {

/**

* Perform static checking whether the given method matches.

*

If this returns {@code false} or if the {@link #isRuntime()}

* method returns {@code false}, no runtime check (i.e. no

* {@link #matches(java.lang.reflect.Method, Class, Object[])} call)

* will be made.

* @param method the candidate method

* @param targetClass the target class

* @return whether or not this method matches statically

*/

boolean matches(Method method, Class> targetClass);

/**

* Is this MethodMatcher dynamic, that is, must a final call be made on the

* {@link #matches(java.lang.reflect.Method, Class, Object[])} method at

* runtime even if the 2-arg matches method returns {@code true}?

*

Can be invoked when an AOP proxy is created, and need not be invoked

* again before each method invocation,

* @return whether or not a runtime match via the 3-arg

* {@link #matches(java.lang.reflect.Method, Class, Object[])} method

* is required if static matching passed

*/

boolean isRuntime();

/**

* Check whether there a runtime (dynamic) match for this method,

* which must have matched statically.

*

This method is invoked only if the 2-arg matches method returns

* {@code true} for the given method and target class, and if the

* {@link #isRuntime()} method returns {@code true}. Invoked

* immediately before potential running of the advice, after any

* advice earlier in the advice chain has run.

* @param method the candidate method

* @param targetClass the target class

* @param args arguments to the method

* @return whether there's a runtime match

* @see MethodMatcher#matches(Method, Class)

*/

boolean matches(Method method, Class> targetClass, Object... args);

/**

* Canonical instance that matches all methods.

*/

MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;

}

PointCut的一部分,用来判断方法是否需要进行增强。ClassFilter过滤需要生成代理的类。而这个类里,不是所有的方法都需要增强的,所以要通过MethodMatcher接口匹配出要增强的方法来。

MethodMatcher分为静态匹配和动态匹配。静态匹配是根据方法名匹配。动态匹配是根据参数进行匹配(不知道这么理解对不对)

MethodMatcher的实现类中,如果isRuntime()方法返回false,则使用静态匹配,无论参数是什么,只要方法名匹配,则都会进行增强。而且这个接口中带有3个参数的matches方法,即matches(java.lang.reflect.Method, Class, Object[])就永远不会执行。

实现类中,如果两个参数的matches方法返回true,且isRuntime()也返回true。那么在执行增强之前,会执行三个参数的matches方法,来判断这个增强是否要执行。

下面来看接口三个方法的注释:

boolean matches(Method method, Class> targetClass);

静态核对给定的方法是否需要增强。如果返回false。则不再会执行三个参数的matches方法。

boolean isRuntime();

当两个参数的matches方法返回true时,是否要执行三个参数的matches方法。该方法在AOP代理生成的时候执行,而不是每次调用代理方法之前执行。意思就是生成代理对象的时候,就已经判断好要不要执行三个参数的matches方法了。

boolean matches(Method method, Class> targetClass, Object... args);

该方法执行的时机是增强方法要执行之前,判断参数是否满足要求,如果满足,则执行增强。注意isRuntime方法是创建代理对象时就决定好的,而是否执行三个参数的matches方法是调用增强之前判断的。

总结

从上面的源码可以看出,PointCut就是起到过滤的作用,首先是过滤类,然后再过滤方法,筛选出需要加强的方法来。由接口可知,我们要将参数中的class或method进行比较,然后过滤,那么,和谁进行比较呢?要过滤的类和方法的规则存在哪里了呢?请看下回分解。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java日常练习题,每天进步一点点(64)
下一篇:Hadoop源码分析六启动文件namenode原理详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~