Spring AOP的两种实现

本文介绍了Spring AOP的两种实现方式:注解方式和XML方式。注解方式中,切面类通过@Aspect注解定义,利用@Before、@After等注解确定织入点。连接点通过@Pointcut定义。配置类启用@EnableAspectJAutoProxy开启自动代理。XML方式下,切面类不再使用注解,而是通过XML配置文件定义切点和通知。

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


Spring AOP有两种实现方式,一种是基于注解的,另一种是基于xml的。

注解方式实现AOP
  • 首先介绍基于注解的实现方式,实现需要有切面类和连接点两个主要的东西。切面类定义了在执行要拦截方法前后执行的方法。而连接点就是指要拦截的方法。
  • 连接点printRole(),首先定义一个接口:
public interface RoleService {
	
	public void printRole(Role role);
}

实现类

@Component
public class RoleServiceImpl implements RoleService {
	
	@Override
	public void printRole(Role role) {
		System.out.println("{id: " + role.getId() + ", " 
	        + "role_name : " + role.getRoleName() + ", "
	        + "note : " + role.getNote() + "}");
	}
}

下面是切面类:

@Aspect
public class RoleAspect {

	@Pointcut("execution(* com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
	public void print() {
	}

	@Before("print()")
	// @Before("execution(*
	// com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
	public void before() {
		System.out.println("before ....");
	}

	@After("print()")
	// @After("execution(*
	// com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
	public void after() {
		System.out.println("after ....");
	}

	@AfterReturning("print()")
	// @AfterReturning("execution(*
	// com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
	public void afterReturning() {
		System.out.println("afterReturning ....");
	}

	@AfterThrowing("print()")
	// @AfterThrowing("execution(*
	// com.ssm.chapter11.aop.service.impl.RoleServiceImpl.printRole(..))")
	public void afterThrowing() {
		System.out.println("afterThrowing ....");
	}

	@Around("print()")
	public void around(ProceedingJoinPoint jp) {
		System.out.println("around before ....");
		try {
			jp.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("around after ....");
	}
}
  • @Aspect注解的类会被Spring IoC容器理解为一个切面。
  • 稍微详细的说一下切面类。切面类中的方法通过注解能够被合理地织入执行流程当中。
  • 这几个注解分别都是其字面的意思,在代理对象方法调用之前,之后调用,around注解将代理方法环绕起来,并用环绕通知代替它。
  • @Pointcut注解定义了一个切点,下面的通知方法都是通过引用它来决定对哪个方法进行织入。具体AspectJ的指示器有很多种,我们常用的是上面所示的execution,详细参阅其他资料。
  • 基于注解的开发方式都少不了配置类,下面定义配置类:
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.ssm.chapter11.aop")
public class AopConfig {
	
	@Bean
    public RoleAspect getRoleAspect() {
        return new RoleAspect();
    }
}

其中注解@EnableAspectJAutoProxy表示开启自动代理功能。如果在XML中进行配置时,则为以下方式,首先引入AOP命名空间,其中的aop:aspectj-autoproxy也是开启自动代理功能。

<?xml version='1.0' encoding='UTF-8' ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd        
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
	<aop:aspectj-autoproxy />
	<bean id="roleAspect" class="com.ssm.chapter11.aop.aspect.RoleAspect" />
	<bean id="roleService" class="com.ssm.chapter11.aop.service.impl.RoleServiceImpl" />
</beans>

以上是通过注解方式实现AOP,当然配置可以使用java配置类,也可以使用xml文件。测试一下:

ApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
Role role = new Role();
role.setId(1L);
role.setRoleName("role_name_1");
role.setNote("note_1");
RoleService roleService = context.getBean(RoleService.class);
roleService.printRole(role);
xml方式实现AOP

首先还是连接点和切面类,连接点就是要被代理的类,跟上面一样。不再赘述,看切面类,也跟上面差不多,只是注解被去掉了:

public class XmlAspect {

	public void before() {
		System.out.println("before ......");
	}
	
	public void after() {
		System.out.println("after ......");
	}
	
	public void afterThrowing() {
		System.out.println("after-throwing ......");
	}
	
	public void afterReturning() {
		System.out.println("after-returning ......");
	}
	
	public void around(ProceedingJoinPoint jp) {
		System.out.println("around before ......");
		try {
			jp.proceed();
		} catch (Throwable e) {
			new RuntimeException("回调原有流程,产生异常......");
		}
		System.out.println("around after ......");
	}
}

然后是配置文件,采用xml的方式配置:

<?xml version='1.0' encoding='UTF-8' ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

	<bean id="xmlAspect" class="com.ssm.chapter11.xml.aspect.XmlAspect" />
	<bean id="roleService" class="com.ssm.chapter11.xml.service.impl.RoleServiceImpl" />
	
	<aop:config>
		<aop:aspect ref="xmlAspect">
		    <!-- 自定义切点 -->
			<aop:pointcut id="printRole"
				expression="execution(* com.ssm.chapter11.xml.service.impl.RoleServiceImpl.printRole(..))" />
			<!-- 定义通知 -->
			<aop:before method="before" pointcut-ref="printRole" />
			<aop:after method="after" pointcut-ref="printRole" />
			<aop:after-throwing method="afterThrowing"
				pointcut-ref="printRole" />
			<aop:after-returning method="afterReturning"
				pointcut-ref="printRole" />
			<aop:around method="around" pointcut-ref="printRole" />
		</aop:aspect>
	</aop:config>
</beans>

测试一下:

ApplicationContext ctx 
   = new ClassPathXmlApplicationContext("spring-cfg4.xml");
RoleService roleService = ctx.getBean(RoleService.class);
RoleVerifier roleVerifier = (RoleVerifier) roleService;
Role role = new Role();
role.setId(1L);
role.setRoleName("role_name_1");
role.setNote("note_1");
roleService.printRole(role);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值