Spring AOP的实现机制(三)---@AspectJ形式的Spring AOP和基于Schema的AOP

本文介绍了Spring AOP的三种使用方式:1.x版本的基于接口定义方式、@AspectJ形式及基于Schema的AOP配置方式,并对比了各自特点。

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

<span style="font-size:18px;">1、@AspectJ形式的Spring AOP
  @AspectJ代表一种定义Aspect的风格,它让我们能够以POJO的形式定义Aspect,没有其它接口限制。唯一需要的,就是使用相应的注解标注这些Aspect定义的POJO类。之后SpringAOP会根据标注的注解搜索这些Aspect定义类,
  然后将其织入系统。
  其实SpringAOP只使用AspectJ的类库进行Pointcut的解析和匹配,最终的实现机制还是Spring AOP最初的架构,也就是使用代理模式处理横切逻辑的织入。
  定义一个切面类的一般方法为:
  使用@Aspect标注Aspect类,@Pointcut的注解指定Pointcut定义,@Around等注解指定哪些方法定义了相应的Advice逻辑
  通过一个来说明
  @Aspect
  public class PerformanceTraceAspect {

	private final Log logger=LogFactory.getLog(PerformanceTraceAspect.class);
	@Pointcut("execution(public void *.method1())||execution(public void *.method2())")
	public void pointcutName(){}
	
	@Around("pointcutName()")
	public Object performanceTrace(ProceedingJoinPoint joinpoint)throws Throwable
	{
		try{
			System.out.println("start.......");
			return joinpoint.proceed();
		}finally{
			System.out.println("stop......");
			if(logger.isInfoEnabled()){
				logger.info("PT in method["+joinpoint.getSignature().getName()+"]>>>>>");
			}
		}
	}
  }
  
  public class Foo {

	public void method1(){
		System.out.println("method1 execution");
	}
	public void method2(){
		System.out.println("method2 execution");
	}
	
	public void method3(){
		System.out.println("method3 execution");
	}
	
	public void doSomething(String str){
		System.out.println(str+"do something");
	}
 }
 
 (1)通过编程方式织入:
 public class aspectProgrammingTest {
	@Test
	public void test() {
		AspectJProxyFactory weaver=new AspectJProxyFactory();
		weaver.setProxyTargetClass(true);
		weaver.setTarget(new Foo());
		weaver.addAspect(PerformanceTraceAspect.class);
		Object proxy=weaver.getProxy();
		((Foo)proxy).method1();
		((Foo)proxy).method2();
	}
 }
 
 通过自动代理织入
 针对@AspectJ风格的AOP,Spring AOP专门提供了一个AutoProxyCreator实现类进行自动代理,以免去过多编码和配置的工作,
 只需要在IoC容器的配置文件中注册一下AnnotationAwareAspectJAutoProxyCreator就可以了。
 实现如下:
 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"

	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
        <!-- 基于XSD的配置方式 -->
        <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

<!-- 基于DTD的配置方式 -->
	<!-- <bean
		class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator">
		<property name="proxyTargetClass" value="true"></property>
	</bean> -->
	
	<bean id="performanceTraceAspect" class="aop.spring.aspectTest.YourAspect"/>
	
	<bean id="target" class="aop.spring.aspect.Foo"/>
	
</beans>


测试类:
public class aspectXmlTest {
	@Test
	public void test() {
		ApplicationContext ctx=new ClassPathXmlApplicationContext("/beans.xml");
		Object proxy=ctx.getBean("target");
		((Foo)proxy).method1();
		((Foo)proxy).method2();
		((Foo)proxy).doSomething("zhsi...");
	}
}

2、基于Schema的AOP

新的基于Schema的AOP配置方式,针对Pointcut、Advisor以及Aspect等概念提供了独立的配置元素,所有这些配置元素都包含在统一的
配置元素中,即<aop:config>
<aop:config>有三个子元素,分别是<aop:pointcut>、<aop:advisor>、 <aop:aspect>.它们三个必须按照顺序进行配置
实现的例子如下:
基于Schema的Advice声明也分为两部分,即Advice的定义和Advice的到容器的配置

Advice的定义如下:
public class SchemaBaseAspect {

	public void doBefore(JoinPoint jp){
		System.out.println("before method[ "+jp.getSignature().getName()+" ] execution");
	}
	
	public void doAfterReturning(JoinPoint jp){
		System.out.println("method["+jp.getSignature().getName()+"]completed successfully");
	}
	
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("around start.....");
		Object reVal=pjp.proceed();
		System.out.println("around end....");
		return reVal;
	}
}

配置声明如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"

	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<bean id="schemaBaseAspect" class="com.aop.spring.SchemaBaseAspect"></bean>

	<aop:config>
		<aop:aspect id="myAspect" ref="schemaBaseAspect" order="2">
			<aop:pointcut id="privatepoint" expression="execution(public void *.doSth())"></aop:pointcut>
			<aop:before pointcut-ref="privatepoint" method="doBefore"></aop:before>
			<aop:after-returning pointcut-ref="privatepoint" method="doAfterReturning"></aop:after-returning>
			<aop:around pointcut-ref="privatepoint" method="doAround"></aop:around>
		</aop:aspect>
	</aop:config>
	
	<bean id="targetFoo" class="com.aop.spring.TargetFoo"></bean>
</beans>

测试类如下:

public class XSDTest {
	@Test
	public void test() {
		ApplicationContext ctx=new ClassPathXmlApplicationContext("beans1.xml");
		TargetFoo f=(TargetFoo) ctx.getBean("targetFoo");
		f.doSth();
	}
}

对于Introduction类型的advice有其独特的实现方式,这里就不再详细介绍了。


到目前为止,我们接触了如下三种Spring AOP的使用方式
(1) Spring AOP 1.x 版本发布的基于接口定义的Advice声明方式。这种方式的特点是,各种类型的Advice定义需要实现特定的接口,Advice的管理可以通过IoC
容器或者直接编程来进行。我们将其称为第一代Spring AOP
(2)@AspectJ形式的AOP是在Spring2.0发布之后新增加的一种Spring AOP使用方式。在这种方式中,我们只需要以POJO的形式声明相应的Aspect和Advice,然后通过
相应的注解标注一下即可,
(3)基于Schema的AOP也是在Spring2.0发布之后增加的Spring AOP使用方式,它融合了第一代Spring AOP和@AspectJ 形式的优点,不但完全支持第一代Spring AOP
的配置需求,而且在@Aspect形式的AOP的基础之上进行了改装:我们依然可以通过POJO声明Aspect和Advice定义,不过,通过相应
注解表达的各种信息,转移到了XSD形式的容器配置文件中。

  对于如何在这三种方式之间进行选择,应该依照当前应用环境、各种工具支持、整体团队对各种方式的熟悉程度等不同情况来权衡利弊,最终决定一种合适的方式。
  目前对于我来说,我还只是在学习阶段,所以对于选择哪一种Spring AOP 方式我还不是有所体会。
  
   what do you want?  </span>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值