Spring AOP APIS

1:Pointcut API in Spring

(1): Cut Point Interface Definition

org.springframework.aop.PointcutInterface is the central interface. Used to Advice(通知)定位到特定的类和方法.

public interface Pointcut {
    ClassFilter getClassFilter();
    MethodMatcher getMethodMatcher();
}

ClassFilterInterface classes used to determine the cut point of action. If the matches()method always returns true, all the goals are matched.

 
public interface ClassFilter {
    boolean matches(Class clazz);
}

MethodMatcherInterface is usually more important.

public interface MethodMatcher {
    boolean matches(Method m, Class targetClass);
    boolean isRuntime();
    boolean matches(Method m, Class targetClass, Object[] args);
}

Most MethodMatcherimplementations are static, meaning that their isRuntime()return false. For this reason, the three parameters of the matchesmethod is never called.

`Note:

If possible, let the cut-off point for the static, allowing the AOP framework to cache the results point cut when an AOP proxy is created.

(2): cut-point operation

Spring supports operations have cut point joint (union) and the intersection (intersection). Joint means that the method can be any of a match, the intersection

It means that all the cut points are matched. However, the use AspectJ point expressionis generally easier.

AspectJExpressionPointcut:AspectJ point expression

(3): it points to achieve Liqie

  • Static cut-off point (Static Pointcuts)

    Based on static entry point 方法和目标类, can not be considered a method parameter. For most purposes, the static and the best entry point enough. The first call method, Spring only assess a static entry point. After that, without the use of each method call to re-evaluate the starting point.

  • Regular Expression entry point (Regular Expression Pointcuts)

    • JdkRegexpMethodPointcut: JDK support for regular expressions. You can set up a list of regular expressions, either to meet that cut-off point for the assessment true.

  • Dynamic contact point (Dynamic Pointcuts)

Dynamic cut-off point to assess the cost of higher cost than static. Consider the method parameters and static information. This means that you must use every method call to evaluate them, and can not be cached, as arguments will vary.

  • Control flow tangent point (Control Flow Pointcuts)

    And the AspectJ cflowsimilar.

(4): parent tangential point (Pointcut Superclasses)

Since static pointcutsmost useful StaticMethodMatcherPointcut. Use example:

 
class TestStaticPointcut extends StaticMethodMatcherPointcut {
    public boolean matches(Method m, Class targetClass) {
        // return true if custom criteria match
    }
}

2:Advice API in Spring

(1): Notification life cycle

Each is a notification Spring Bean. 通知示例可以在所有通知对象之间共享.

(2): Spring notification type

Around Advice (around advice)

Spring most basic advice is around advice. Use method interception. Class implementation MethodInterceptor.

 
public interface MethodInterceptor extends Interceptor {
    
    /**
     * Implement this method to perform extra treatments before and
     * after the invocation. Polite implementations would certainly
     * like to invoke {@link Joinpoint#proceed()}.
     * @param invocation the method invocation joinpoint
     * @return the result of the call to {@link Joinpoint#proceed()};
     * might be intercepted by the interceptor
     * @throws Throwable if the interceptors or the target object
     * throws an exception
     */
    Object invoke(MethodInvocation invocation) throws Throwable;
}
/**
 * Description of an invocation to a method, given to an interceptor
 * upon method-call.
 *
 * <p>A method invocation is a joinpoint and can be intercepted by a
 * method interceptor.
 */
public interface MethodInvocation extends Invocation {
    /**
     * Get the method being called.
     * <p>This method is a frienly implementation of the
     * {@link Joinpoint#getStaticPart()} method (same result).
     * @return the method being called
     */
    Method getMethod();
}
public interface Invocation extends Joinpoint {
    /**
     * Get the arguments as an array object.
     * It is possible to change element values within this
     * array to change the arguments.
     * @return the argument of the invocation
     */
    Object[] getArguments();
}
public interface Joinpoint {
    /**
     * Proceed to the next interceptor in the chain.
     * <p>The implementation and the semantics of this method depends
     * on the actual joinpoint type (see the children interfaces).
     * @return see the children interfaces' proceed definition
     * @throws Throwable if the joinpoint throws an exception
     */
    Object proceed() throws Throwable;
    /**
     * Return the object that holds the current joinpoint's static part.
     * <p>For instance, the target object for an invocation.
     * @return the object (can be null if the accessible object is static)
     */
    Object getThis();
    /**
     * Return the static part of this joinpoint.
     * <p>The static part is an accessible object on which a chain of
     * interceptors are installed.
     */
    AccessibleObject getStaticPart();
}
 

invoke () method of MethodInvocationthe parameters is disclosed a method is invoked, the target point of attachment, AOP parameters agents and methods. invoke () method should return the call: 连接点的返回值.

Before Advice (pre-notification)

Simpler advice type is a before advice. You do not need to MethodInvocationobject. It is 进入方法之前调用.

Pre-notification 主要优点不需要调用proceed()方法, we will not inadvertently not continue to intercept chain.

 
public interface MethodBeforeAdvice extends BeforeAdvice {
    void before(Method m, Object[] args, Object target) throws Throwable;
}

Spring API design allows field provided prior notice, although the usual objects apply to field interception, but Spring is unlikely to achieve it. Please note that the return type void. In advice can insert custom behavior before connecting point of execution but can not change until the return value. If before advice throws an exception, it will suspend further implementation of the interceptor chain. Abnormal propagated back to the interceptor chain.

返回所有方法的调用次数

 
public class CountingBeforeAdvice implements MethodBeforeAdvice {
    private int count;
    public void before(Method m, Object[] args, Object target) throws Throwable    {
        ++count;
    }
    public int getCount() {
        return count;
    }
}

Throws Advice (abnormality notice)

After returning abnormality notification connection point, the connection point if Ran abnormal, the notification is invoked. ThrowsAdviceThe interface is a marker interface, inherited AfterAdvice. Examples are as follows: abnormal parameters must be present, other parameters like method, arguments exists, depends on whether you need.

 
public void afterThrowing(Exception ex){
}
public void afterThrowing(RemoteException){
}
public void afterThrowing(Method method, Object[] args, Object target, Exception ex){
}
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex){
}

note

不要抛出与目标签名方法不兼容的未声明的已检查异常

Rear return notification (After Returning Advice)

Rear return notice required to achieve `AfterReturningAdvice`.

 
public interface AfterReturningAdvice extends Advice {
    void afterReturning(Object returnValue, Method m, Object[] args, Object target)
            throws Throwable;
}

Post notifications can be returned 访问返回值(但是它不能修改),被调用的方法,方法参数,目标对象if it throws an exception,

It throws interceptor chain instead of the return value.

统计所有成功调用但是没有抛出异常的方法次数

 
public class CountingAfterReturningAdvice implements AfterReturningAdvice {
    private int count;
    public void afterReturning(Object returnValue, Method m, Object[] args, Object target)
            throws Throwable {
        ++count;
    }
    public int getCount() {
        return count;
    }
}

Introduction advice (Introduction Advice)

Introduction requires a IntroductionAdvisorand IntroductionInterceptor, to achieve the following

 
public interface IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice {
}
public interface DynamicIntroductionAdvice extends Advice {
    /**
     * Does this introduction advice implement the given interface?
     * @param intf the interface to check
     * @return whether the advice implements the specified interface
     */
    boolean implementsInterface(Class<?> intf);
}

invoke()Methods inherited AOP aopalliance MethodInterceptorinterface. If the method call on the interface introduced

The introduction interceptor is responsible for handling calls, it can not be called proceed().

Introducing notification can not be applied to any point of the cut. 它仅适用于类,而不是方法级别的。Only IntroductionAdvisorthe introduction of notification use.

 
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
    ClassFilter getClassFilter();
    void validateInterfaces() throws IllegalArgumentException;
}
public interface IntroductionInfo {
    Class[] getInterfaces();
}

Class contains only filter logic. getInterfaces()Returns an interface section introduced. validateInterfaces()A method for determining whether the interface is to be introduced into the IntroductionInterceptorconfiguration.

Class DelegatingIntroductionInterceptoris designed to be a proxy for actual interface to achieve the introduction of the introduced.

3:The Advisor API in Spring

In Spring, Advisorit is contained only one 一个通知对象和一个切点表达式对象关联of 切面.

`DefaultPointcutAdvisor `Most versatile advisor.

(2): Use ProxyFactoryBeanto create AOP proxies

The basic method of creating AOP proxy in Spring is to use ProxyFactoryBean. He can completely control the entry points, as well as any applicable notice their order.

JavaBean properties

Some key property is inherited from ProxyConfig.

  • proxyTargetClass: 如果代理的是目标类,而不是接口,该值为true。Default false.

  • optimize: Controls whether the agency will actively optimize application created by CGLIB. Unless you fully understand the relevant AOP optimization, otherwise this setting should not be used lightly.

  • frozen: If the proxy configuration is frozen, no longer allowed to change the configuration. The default is false.

  • exposeProxy: Deciding whether to 当前代理对象暴露到ThreadLocal中,以便可以被目标对象访问. able to pass

AopContext.currentProxy()Obtain.

Other attributes from ProxyFactoryBean.

  • proxyInterfaces: Agent array of interfaces. If not supported, the CGLIB agent is used.

  • interceptorNames: Interceptor array ( Advisor). These names exist in the current bean factory, a factory that contains the ancestors.

  • singleton: Decide whether to return the factory singleton object, by default true.

(3): JDK and CGLIB agent

  • If a target object does not implement any interfaces, use CGLIB agent.

  • If a target object implements any interface, use the default JDK proxy

  • If a target object implements any interface, but the proxyTargetClassproperty is true, use GGLIB agent.

(4): Proxy Interface

interceptorNamesProperty holds a list, this list is 拦截器(MethoInterceptor)or ( Advisor)

In the current factory bean names.

注意:

You may be wondering why the list does not contain bean reference. The reason is that, if ProxyFactoryBean the singleton property is set to false, then it must be able to return independent proxy instances. If any of the consultant is itself a prototype, we need to return a separate instance, and therefore must be able to obtain an instance of the prototype from the factory. Holds a reference is not enough.

(5): Acting Class

Limitations CGLIB agent

  • final methods can not be notified. Because they can not be overridden

  • Spring3.2, CGOLIB repackaged in the spring-core jar.

(6):使用全局(Advisors)

By adding after the interceptor 星号, the program adds advisor all bean name partially match the previous asterisk to the block in the chain. As follows:

 
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="service"/>
    <property name="interceptorNames">
        <list>
            <value>global*</value>
        </list>
    </property>
</bean>
<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>

(7): Use ProxyFactoryto create AOP proxies

一个目标对象,一个通知,一个顾问。

   @Bean
    public AspectJProxyFactory aspectJProxyFactory() {
        AspectJProxyFactory proxyFactoryBean = new AspectJProxyFactory(new UserService());
        String expression = "execution(* com.ley.springboot.UserService.*(..))";
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(expression);
        Advice advice = new UserServiceMethodBeforeAdvice();
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
        proxyFactoryBean.addAdvisor(advisor);
        return proxyFactoryBean;
    }
    @Bean(name = "proxyFactoryBean")
    public ProxyFactoryBean proxyFactoryBean() {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
        proxyFactoryBean.setTarget(new UserService());
        String expression = "execution(* com.ley.springboot.UserService.*(..))";
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(expression);
        Advice advice = new UserServiceMethodBeforeAdvice();
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
        proxyFactoryBean.addAdvisors(advisor);
        return proxyFactoryBean;
    }
ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addAdvice(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();

(8): notification object manipulation

AdvisedThe interface is used to manipulate notification object.

 
Advisor[] getAdvisors();
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice) throws AopConfigException;
void addAdvisor(Advisor advisor) throws AopConfigException;
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
int indexOf(Advisor advisor);
boolean removeAdvisor(Advisor advisor) throws AopConfigException;
void removeAdvisor(int index) throws AopConfigException;
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
boolean isFrozen();

 

 

You can be added DefaultPointcutAdvisor,它持有一个pointcut和advised. And it may be used to add any

Advisor

(9): Use auto-proxyStrategy

  • BeanNameAutoProxyCreator: This class is an BeanPostProcessorautomatically created based on the name of the bean AOP

    proxy.

 
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames" value="jdk*,onlyJdk"/>
    <property name="interceptorNames">
        <list>
            <value>myInterceptor</value>
        </list>
    </property>
</bean>
 
  • DefaultAdvisorAutoProxyCreatorVersatile and more powerful auto proxy creator. The program will automatically add the application meets advisor in the current context, without the need to include specific bean name in the bean definition auto-proxy advisor's.该类在将相同建议一致的应用于许多业务对象很有用。例如跟踪或者性能监视方面。

(10): Define a new notification type

org.springframework.aop.framework.adapterPackage is a SPIpackage, extended new notification type. Customize the new notification type only constraint is that it must implement the org.aopalliance.aop.Advicemarker interface.

Guess you like

Origin www.cnblogs.com/liuenyuan1996/p/11093742.html