官术网_书友最值得收藏!

Operations on Pointcut

The Pointcut class exposes two methods for the union and intersection of pointcuts.

public static Pointcut union (Pointcut a, Pointcut b)
public static Pointcut intersection (Pointcut a, Pointcut b)

The union of two pointcuts is the pointcut matching any method matched by either pointcut (Boolean OR). The intersection matches only methods matched by both pointcuts (Boolean AND).

Pointcuts can be composed using the static methods in the org.springframework.aop.support.Pointcuts (union and intersection) class, or using the ComposablePointcut class in the same package.

ComposablePointcut

The ComposablePointcut class is used to compose two or more pointcuts together with operations such as union() and intersection().

The full qualified name of the class is:

org.springframework.aop.support.ComposablePointcut

By default, ComposablePointcut is created with a ClassFilter that matches all the classes and a MethodMatcher that matches all the methods.

We can supply our own initial ClassFilter and MethodMatcher if we like:

ComposablePointcut(ClassFilter classFilter, MethodMatcher methodMatcher)

The union() and intersection() methods are both overloaded to accept ClassFilter and MethodMatcher arguments.

Invoking the union() method, the MethodMatcher of ComposablePointcut is replaced with a UnionMethodMatcher that uses the current MethodMatcher of the ComposablePointcut and the MethodMatcher passed to the union() method as arguments.

The UnionMethodMatcher method then returns true for a match if either of its wrapped MethodMatchers returns true.

This way it is possible to invoke the union() method as many times as we want, with each call creating a new UnionMethodMatcher that wraps the current MethodMatcher with the MethodMatcher passed to union().

Internally, the intersection() method works in a similar way to the union ().

Here is the target class:

package org.springaop.chapter.two.pointcut;
import java.util.Date;
public class ComposableTargetExample {
public ComposableTargetExample() {
startDate = new Date();
}
public ComposableTargetExample(String description) {
startDate = new Date();
this.description = description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public Date getStartDate() {
return (Date) startDate.clone();
}
private Date startDate;
private String description;
}

Here is the example class:

package org.springaop.chapter.two.pointcut;
import java.lang.reflect.Method;
import org.springframework.aop.Advisor;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcher;
public class ComposablePointcutExample {
public static void main(String[] args) {
ComposableTargetExample target = new ComposableTargetExample();
ComposablePointcut pc = new ComposablePointcut( ClassFilter.TRUE,
new GetterMethodMatcher());
System.out.println("Test GetterMetodMatcher :");
ComposableTargetExample proxy = getProxy(pc, target);
testInvoke(proxy);
System.out.println("Test GetterMetodMatcher UNION SetterMethodMatcher :");
pc.union(new SetterMethodMatcher());
proxy = getProxy(pc, target);
testInvoke(proxy);
System.out.println("Test (GetterMetodMatcher UNION SetterMethodMatcher) INTERSECT GetStartDateMethodMatcher :");
pc.intersection(new GetStartDateMethodMatcher());
proxy = getProxy(pc, target);
testInvoke(proxy);
}
private static ComposableTargetExample getProxy( ComposablePointcut pc, ComposableTargetExample target) {
Advisor advisor = new DefaultPointcutAdvisor(pc,
new ComposableBeforeAdvice());
ProxyFactory pf = new ProxyFactory();
pf.setTarget(target);
pf.addAdvisor(advisor);
return (ComposableTargetExample) pf.getProxy();
}
private static void testInvoke(ComposableTargetExample proxy) {
proxy.getStartDate();
proxy.getDescription();
proxy.setDescription("New Description");
}
private static class GetterMethodMatcher extends StaticMethodMatcher {
public boolean matches(Method method, Class cls) {
return (method.getName().startsWith("get"));
}
}
private static class GetStartDateMethodMatcher extends StaticMethodMatcher {
public boolean matches(Method method, Class cls) {
return "getStartDate".equals(method.getName());
}
}
private static class SetterMethodMatcher extends StaticMethodMatcher {
public boolean matches(Method method, Class cls) {
return (method.getName().startsWith("set"));
}
}
}

The result will be:

ComposablePointcut

Let's try to see what has been done. We defined a target class (ComposableTargetExample), a ComposableBeforeAdvice that prints "ComposableBeforeAdvice".

To test ComposablePointcut we wrote the ComposableTargetExample class with a main method.

In a getProxy method, we created an advisor that bound pointcuts and advices, created a new ProxyFactory to which we set advisors and target objects, and returned the target object.

In the testInvoke method, we invoked two Get methods and one Set method.

In the Main method, we created the pointcut declaring we wanted to use a GetterMethodMatcher, and we called testInvoke. The result was the application of the advice to two Get methods. Then we made a union of pointcuts that at the beginning contained the GetterMethodMatcher with a SetterMethodMatcher, and then we called the testInvoke method. The result was the application of the advice three times.

Then we make the intersection with a GetStartDateMethodMatcher, and call the testInvoke method. The result is the application of advice only on the method that satisfies the intersection.

ControlFlowPointcut

The ControlFlowPointcut is a pointcut that matches all methods within the control flow of another method—that is, any method that is invoked either directly or indirectly as the result of another method being invoked.

Control flow pointcuts allow us to apply advices to an object in a selective manner depending on the context in which it is executed.

The full qualified name of the class is:

org.springframework.aop.support.ControlFlowPointcut

However, we have to pay attention to the performance we get when using it. The Spring documentation indicates that a control flow pointcut is typically five times slower than other pointcuts on a 1.4 JVM, and ten times slower on a 1.3 JVM.

Here is the target class:

package org.springaop.chapter.two.pointcut;
public class ControlFlowTargetExample {
public void greeting(){
System.out.println("Cheers");
}
}

This is the before advice:

package org.springaop.chapter.two.pointcut;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class ControlFlowBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("ControlFlow beforeAdvice ");
}
}

Here is the example class:

package org.springaop.chapter.two.pointcut;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.ControlFlowPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class ControlFlowPointcutExample {
public static void main(String[] args) {
ControlFlowPointcutExample ex = new ControlFlowPointcutExample();
ex.run();
}
public void run() {
ControlFlowTargetExample target = new ControlFlowTargetExample();
Pointcut pc = new ControlFlowPointcut(ControlFlowPointcutExample.class, "test");
Advisor advisor = new DefaultPointcutAdvisor(pc,
new ControlFlowBeforeAdvice());
ProxyFactory pf = new ProxyFactory();
pf.setTarget(target);
pf.addAdvisor(advisor);
ControlFlowTargetExample proxy = (ControlFlowTargetExample) pf.getProxy();
System.out.println("Trying normal invoke");
proxy.greeting();
System.out.println("Trying under ControlFlowPointcutExample.test()");
test(proxy);
}
private void test(ControlFlowTargetExample bean) {
bean.greeting();
}
}

The result will be:

ControlFlowPointcut

Let's see what has been done. We defined a target class (ControlFlowTargetExample), a ControlFlowBeforeAdvice that prints ControlFlow beforeAdvice.

To test ControlFlowPointcut, we wrote the ControlFlowPointcutExample class with a main method that only calls a run method, where we put the real test body. We did this to show the effects of the flow of a calling of a method from a given class.

The result was that when the method was called directly by the proxy, the advice was not applied, whereas when the call came from within another object (ControlFlowPointcutExample in this case), the advice was applied.

Pointcut constants

For the common operations, pointcut constants are available in this package:

org.springframework.aop.support.Pointcuts

The constants are:

GETTERS is a constant Pointcut object, matching all bean property getters, in any class.

SETTERS is a constant Pointcut object matching all bean property setter in any class.

主站蜘蛛池模板: 安多县| 绵阳市| 阿拉善右旗| 吉林市| 鹤壁市| 永寿县| 肃北| 屯留县| 虹口区| 财经| 时尚| 和田县| 堆龙德庆县| 临夏县| 塔城市| 揭阳市| 于田县| 邓州市| 星座| 福鼎市| 吉木乃县| 绥德县| 张家界市| 房产| 宁德市| 雅安市| 五大连池市| 尼勒克县| 博客| 石楼县| 中江县| 修武县| 行唐县| 长宁区| 石狮市| 雅安市| 海晏县| 北辰区| 车致| 寿阳县| 广饶县|