文章目录
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);