【Spring-AOP】Spring提供的AOP开发方式和底层AOP开发方式

本文详细介绍了Spring AOP的使用,包括切面、切点和增强的实现。通过示例展示了如何定义切点、通知,并利用ProxyFactoryBean创建代理。同时,解释了Spring如何通过beanPostProcessor自动代理容器中的类,并提供了调整代理对象增强的API。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring提供的AOP方式

@Component
@Aspect
public class AopAspect {
	@Pointcut(value = "execution(* com.ztryou.service.PersonServiceImpl.*(..))")
	public void pointcut() {
	}

	@Before("pointcut()")
	public void beforeAdvice(JoinPoint point) throws Exception {
		System.out.println("befor");
	}

	@Around(value = "pointcut()")
	public Object aroundAdvice(ProceedingJoinPoint pjp) {
		Object obj = null;
		try {
			System.out.println("around before");
			MethodSignature ms = (MethodSignature) pjp.getSignature();
			Object target = pjp.getTarget();
			Method method = ms.getMethod();

			method.invoke(target, 1);
			obj = pjp.proceed();
			System.out.println("around after");
		} catch (Throwable e) {
			e.printStackTrace();
		}
		return obj;
	}

	/**
	 * 返回后通知:在连接点正常执行完后执行的通知
	 */
	@AfterReturning(value = "pointcut()", returning = "ret")
	public void afterReturningAdvice(Object ret) {
		System.out.println("after return");
	}

	/**
	 * 抛出异常后通知:在连接节点抛出异常退出时执行的通知
	 */
	@AfterThrowing(value = "pointcut()", throwing = "ex")
	public void afterThrowingAdvice(Exception ex) {
		System.out.println("after Throw");
	}

	@After("pointcut()")
	public void afterFinallyAdvice() {
		System.out.println("after");
	}

}

SpringAOP的底层实现

主要设计三个方面:

  1. advisor:切面,切面则包含下面的切点和拦截器
public interface Advisor {
	Advice getAdvice();
	。。。。。
}

public interface PointcutAdvisor extends Advisor {

	Pointcut getPointcut();

}
  1. pointcut: 切点
public interface Pointcut {
	// 用来匹配类
	ClassFilter getClassFilter();
	// 更细粒度的匹配,匹配方法
	MethodMatcher getMethodMatcher();

}
  1. advice:增强(拦截器,用于执行自己的逻辑)
public interface Advice {

}

这里注意,增强只是一个标识接口,用来表示这是一个增强类。我们要增强的逻辑是要实现MethodInterceptor接口,在invoke方法中写的。

public interface MethodInterceptor extends Interceptor {
	Object invoke(MethodInvocation invocation) throws Throwable;
}

每个都有自己的接口,只需要自己实现子类。

Spring提供的现成的类

RegexpMethodPointcutAdvisor类:通过解析正则表达式匹配目标方法。当然它的内部是使用的正则表达式的节点类:JdkRegexpMethodPointcut,开发这直接编写自己的拦截器就好。

使用:

<bean id="settersAndAbsquatulateAdvisor"
        class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    <property name="advice">
        <ref bean="beanNameOfAopAllianceInterceptor"/>
    </property>
    // 这里要设置你想拦截的方法的表达式。
    // 这个表达式会复制给切点类JdkRegexpMethodPointcut
    <property name="patterns">
        <list>
            <value>.*set.*</value>
            <value>.*absquatulate</value>
        </list>
    </property>
</bean>

DefaultPointcutAdvisor这个类只是一个切面类,需要自己定义切点和增强。默认的切点是匹配所有的类,如果这样符合预期,那么只需要定义增强类。

增强的拦截

增强的逻辑是放在拦截器中执行的:

public class DebugInterceptor implements MethodInterceptor {
	// MethodInvocation 是一个拦截器执行链,调用proceed()会执行下一个拦截器。
	// 所以可以在proceed()前后执行自己的逻辑。
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Before: invocation=[" + invocation + "]");
        Object rval = invocation.proceed();
        System.out.println("Invocation returned");
        return rval;
    }
}

使用ProxyFactoryBean创建代理

一般创建代码的时候,spring通过bean的postBeanProcessor处理器,对bean进行拦截,创建代理。还有一种方法就是通过ProxyFactoryBean创建代理,但是这种方式只能对一个bean进行代理。例子可以看:TransactionProxyFactoryBean

使用spring aop自己创建代理

ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
factory.addAdvice(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();

自动代理

之前介绍的都是代理一个指定类。那么spring是如何代理容器的类呢?使用的是beanPostProcessor处理器。在初始化后方法中,找到所有切面类,对该bean进行匹配。如果符合,就代理。

包装代理对象

org.springframework.aop.framework.Advised接口实现了可以对代理对象的所有操作。

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();

封装之后可以进行调节:

Advised advised = (Advised) myObject;
Advisor[] advisors = advised.getAdvisors();
int oldAdvisorCount = advisors.length;
System.out.println(oldAdvisorCount + " advisors");

// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(new DebugInterceptor());

// Add selective advice using a pointcut
advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));

assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值