版权声明:仅供学习交流使用 https://blog.csdn.net/drxRose/article/details/84867195
基于代理的spring aop中,使用接口Advisor表示切面.
- 对目标对象织入通知可使用PointAdvisor接口及其子类,定义切面.其子类中有便捷的DefaultPointcutAdvisor实现类可使用.
- 对目标对象织入引入功能时,可使用IntroductionAdvisor接口.
- 切面即切点和通知的组合,可使用DefaultPointcutAdvisor来定义切点和通知.
- org.springframework.aop.Pointcut的结构
- org.aopalliance.aop.Advice的结构
关于PointCut的实现,又需要有ClassFilter和MethodMatcher来匹配目标对象类型和目标对象的方法.
目标对象类
package siye;
public class TargetObj_reuse
{
public void work()
{
System.out.println("work....");
}
public void wake(int num)
{
System.out.println("user_wake..." + num);
}
}
对目标对象引入新特性的接口
package siye;
public interface NewFeature
{
void eat();
}
前置通知实现类
package siye;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeAdviceImpl implements MethodBeforeAdvice
{
@Override
public void before(Method method, Object[] args,
Object target) throws Throwable
{
System.out.println("方法即将被调用.");
}
}
引入实现类
package siye;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
public class IntroductionAdviceImpl extends
DelegatingIntroductionInterceptor implements
NewFeature
{
private static final long serialVersionUID =
-543070161703560988L;
@Override
public Object invoke(MethodInvocation mi)
throws Throwable
{
return super.invoke(mi);
}
@Override
public void eat()
{
System.out.println("eat...");
}
}
目标对象类型匹配简单实现类
package siye;
import org.springframework.aop.ClassFilter;
public class GenericClassFilterImpl implements ClassFilter
{
@Override
public boolean matches(Class<?> clazz)
{
if (TargetObj_reuse.class.isAssignableFrom(clazz))
{// 在此,可配置要切入的对象类型的集合.
return true;
}
return false;
}
}
切点实现类,包含多种情况切点是切点实现的非共有类
package siye;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.DynamicMethodMatcher;
import org.springframework.aop.support.StaticMethodMatcher;
/**
* 标记接口
*/
public interface AllPointcut
{
}
/**
* 定义静态方法切点
* 类说明:
* MyStaticPointcutImpl,实现切点.
* StaticMethodMatcherImpl,实现方法匹配.
*/
class MyStaticPointcutImpl implements Pointcut
{// 定义方法和类型匹配
@Override
public ClassFilter getClassFilter()
{
return new GenericClassFilterImpl();
}
@Override
public MethodMatcher getMethodMatcher()
{
return new StaticMethodMatcherImpl();
}
}
class StaticMethodMatcherImpl extends StaticMethodMatcher
{// 定义静态方法匹配
@Override
public boolean matches(Method method,
Class<?> targetClass)
{
if ("work".equals(method.getName()))
{
return true;
}
return false;
}
}
/**
* 定义动态方法切点.
* 接口DynamicMethodMatcher.
* Convenient abstract superclass for dynamic method matchers,
* which do care about arguments at runtime.
*
* MyDynamicPointcutImpl,实现切点.
* DynamicMethodMatcherImpl,实现方法匹配.
*/
class MyDynamicPointcutImpl implements Pointcut
{// 定义方法和类型匹配
@Override
public ClassFilter getClassFilter()
{
return new GenericClassFilterImpl();
}
@Override
public MethodMatcher getMethodMatcher()
{
return new DynamicMethodMatcherImpl();
}
}
class DynamicMethodMatcherImpl extends DynamicMethodMatcher
{
@Override
public boolean matches(Method method,
Class<?> targetClass, Object... args)
{
if (Pattern.matches("^w\\w+$", method.getName())
&& args.length > 0)
{// 匹配以开头且有参数的方法
// System.out.println(targetClass);
return true;
}
return false;
}
}
测试类
package siye;
import org.aopalliance.aop.Advice;
import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
public class UnitTest
{
TargetObj_reuse targetObj;// 声明目标对象
Advice adviceImpl;// 声明通知实现
DefaultPointcutAdvisor advisor;// 声明切面
ProxyFactory proxyFactory; // 声明代理工厂
Pointcut pointcutImpl; // 声明切点
@Before
public void prepare()
{
// 实例化目标对象
targetObj = new TargetObj_reuse();
// 实例化前置通知
adviceImpl = new BeforeAdviceImpl();
// 实例化通用的切面
advisor = new DefaultPointcutAdvisor();
// 实例化代理工厂
proxyFactory = new ProxyFactory();
// 设置目标代理
proxyFactory.setTarget(targetObj);
// 强制使用cglib代理
proxyFactory.setProxyTargetClass(true);
}
@Test
public void testStaticAspect()
{
pointcutImpl = new MyStaticPointcutImpl();
advisor.setPointcut(pointcutImpl);// 设置切面的切点
advisor.setAdvice(adviceImpl); // 设置切面的通知
proxyFactory.addAdvisor(advisor);
TargetObj_reuse obj =
(TargetObj_reuse) proxyFactory.getProxy();
obj.work();// 前置通知对此类的此方法生效
}
@Test
public void testDynamicAspect()
{
pointcutImpl = new MyDynamicPointcutImpl();
// 设置切面的切点
advisor.setPointcut(pointcutImpl);
// 设置切面的通知
advisor.setAdvice(adviceImpl);
proxyFactory.addAdvisor(advisor);
TargetObj_reuse obj =
(TargetObj_reuse) proxyFactory.getProxy();
obj.work();
obj.wake(12);
}
@Test
public void testIntroductionAspect()
{
// 因引入,要使用此通知器.
Advice advice = new IntroductionAdviceImpl();
Advisor advisor =
new DefaultIntroductionAdvisor(advice);
proxyFactory.addAdvisor(advisor);
TargetObj_reuse obj0 =
(TargetObj_reuse) proxyFactory.getProxy();
obj0.work();
NewFeature obj1 = (NewFeature) obj0;
obj1.eat();
}
}
- 基于xml的实现,可借用ProxyFactoryBean来实现,具体的实现区别是设置其属性.
- 可直接实现Advisor接口下的特定通知器,来完成自定义的切面(方法与上类似).
- 也可直接实现Pointcut接口下的特定通知器,来完成自定义的切面(方法与上类似).
- 以上的代码实例,是以实现MethodMatcher接口下的特定接口或类来实现的.
Advisor接口下的特定切面 | Pointcut接口下的特定切点 | MethodMatcher接口下的匹配方法 |
DefaultIntroductionAdvisor | StaticMethodMatcherPointcut | ControlFlowPointcut |
DefaultPointcutAdvisor | DynamicMethodMatcher | DynamicMethodMatcher |
NameMatchMethodPointcutAdvisor | AnnotationMethodMatcher | StaticMethodMatcher |
RegexpMethodPointcutAdvisor | ExpressionPointcut | TrueMethodMatcher |
StaticMethodMatcherPointcutAdvisor | ControlFlowPointcut | IntroductionAwareMethodMatcher |
e.g. | ComposablePointcut | e.g. |
e.g. |