目录
- SpringAOP的Aspectj方式实现
- 前提
- 之前的方式有问题:
- 解决:
- 实现:
- 使用
- Acspectj和SchemaBased的异同
- 1. 相同点:
- 2. 不同点:
- SpringAOP的切点的声明格式
- 注解
- ① @Component
- ② @Service
- ③ @pointcut
- ④ @Aspect
- ⑤ @Before
- ⑥ @After
- ⑦ @Around
- ⑧ @AfterThrowing
SpringAOP的Aspectj方式实现
前提
实现功能的扩展,可以在springAop下有一个这个方式进行实现。这个就是Aspectj.
之前的前置通知那些操作,就是SchemaBase方式实现功能的扩展。 现在也是实现功能的扩展,只是用不同的方式,现在的方式是Aspectj。
之前的方式有问题:
目前我们已经能够使用SpringAOP的SchemaBased方式来实现功能扩展。在使用SchemaBased方式实现功能扩展时,发现一个扩展代码就需要声明对应的实现了指定的接口的类,这样造成代码的结构体系过于繁杂。一个通知一个类。
解决:
在一个类中声明所有的通知方法。这样又会造成Spring容器无法区分该类中的方法那些是前置,那些是后置,那些是环绕,那些是异常了,怎么办?在配置文件中的切面配置中,指明哪些方法是前置,哪些是后置即可。
实现:
SpringAOP的AspectJ方式
SpringAOP的SchemaBased方式来实现功能扩展,需要使用接口,spring容器是需要通过接口才可以知道哪些是前置通知,哪些是后置通知。
现在使用Aspectj这个方式,我们就可以直接在xml里面告诉spring容器,哪些是前置通知,哪些是后置通知。
使用
我们现在就可以将很多的通知都写在一个类里面,并且不需要继承其他的接口。
将这个类需要在xml里面进行配置,并且需要在配置规则里面告诉spring容器,哪些是前置,哪些是后置。
代码语言:javascript复制public class MyAdvice {
//前置通知
public void before(String name,int age){
System.out.println("我是前置通知" name age);
}
/*//后置通知
public void after(){
System.out.println("我是后置通知");
}
//环绕通知
参数必须是这样,这个是给spring看的
public void myRound(ProceedingJoinPoint pp) throws Throwable {
//环绕前
System.out.println("环绕-前");
//放行
Object proceed = pp.proceed();
//环绕后
System.out.println("环绕-后");
}
//异常通知
public void myThrow(Exception ex){
System.out.println("我是异常通知:" ex.getMessage());
}*/
代码语言:javascript复制 <!--配置学生的bean-->
<bean id="stu" class="com.pojo.Student"></bean>
<!--配置通知bean-->
<bean id="advice" class="com.advice.MyAdvice"></bean>
<!--配置组装规则-->
<aop:config>
ref这个属性就是告诉从哪一个类里面找方法
<aop:aspect ref="advice"><!--声明通知bean的ID-->
<!--声明切点-->
<aop:pointcut id="mp" expression="execution(* com.pojo.Student.testStudent(String,int)) and args(name,age)"/>
<!--前置通知-->
<aop:before method="before" pointcut-ref="mp" arg-names="name,age"></aop:before>
<!--<!–后置通知–>
<aop:after-returning method="after" pointcut-ref="mp"></aop:after-returning>
<!–环绕通知–>
<aop:around method="myRound" pointcut-ref="mp"></aop:around>
<!–异常通知–>
throwing写的是异常通知的形参名字
<aop:after-throwing method="myThrow" pointcut-ref="mp" throwing="ex"></aop:after-throwing>-->
</aop:aspect>
</aop:config>
<aop:aspect是新的标签,在这个标签下面就可以进行写了
Acspectj和SchemaBased的异同
1. 相同点:
在不修改源码的情况下都能实现功能的扩展。
2. 不同点:
(1) SchemaBased方式基于接口来区别前置和后置和环绕和异常通知的,而AspectJ方式是在配置文件中使用标签来区分。
(2) AspectJ方式在配置中的配置方式发现其切点的声明以及对应的通知组装中,切点只在Aop:aspect标签下有效。而SchemaBased方式声明的切点在全局有效.SchemaBased的切点的通用性比AspectJ方式要好。
SpringAOP的切点的声明格式
① 切点是某包某类的无参数的方法: 示例:
代码语言:javascript复制execution(* com.bjsxt.service.impl.Student.test())
② 切点是某包某类带有参数的方法 示例:
代码语言:javascript复制execution(* com.bjsxt.service.impl.Student.test(String,int))
③ 切点是某包某类的某个同名的所有方法 示例:… 表示任意个数任意类型的参数
代码语言:javascript复制execution(* com.service.impl.Student.test(..))
④ 切点是某包下的某类的所有方法 示例:*表示任意的类名,方法名,包名
代码语言:javascript复制execution(* com.service.impl.Student.*(..))
⑤ 切点是某包下的所有类的所有方法 示例:* 表示任意的类名,方法名,包名
代码语言:javascript复制execution(* com.service.impl.*.*(..))
注解
注意:
SpringAOP的注解方式实现是基于AspectJ方式的。
SchemaBased方式是没有的。
使用:
① 必须在applicationcontext.xml文件中声明注解的使用路径,方便Spring容器对象的扫描,提升扫描效率。
代码语言:javascript复制<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
先写这句话
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
之后写这两句话
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--配置注解扫描路径-->context:component-scan这个标签的使用需要前面的导入
base-package属性是 哪一个包下面的文件需要走注解 多个包用逗号隔开
<context:component-scan base-package="com.advice,com.pojo"></context:component-scan>
<!--配置AOP注解生效-->
<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
① @Component
作用:
相当于配置文件的bean标签,将某个类的对象扫描到Spring容器中。此注解一般在普通Java类上用。
注意:
默认类名的首字母小写即为bean对象的ID,也可以使用注解
的value属性声明自定义的ID,value可以省略不写。
使用:
声明在类上。
② @Service
作用:
相当于配置文件的bean标签,将某个类的对象扫描到Spring容器 中。此注解专门在业务层实体类上使用来表明该类为业务类
注意:
默认类名的首字母小写即为bean对象的ID,也可以使用注解的 value属性声明自定义的ID,value可以省略不写。
③ @pointcut
作用:声明切点
使用:在切点方法上使用
④ @Aspect
作用:声明该类为通知类
使用:结合@Component在通知类上使用
⑤ @Before
作用:声明方法为前置通知方法
使用:在前置通知方法上声明
注意:需要在其中声明对应的切点的全限定路径
⑥ @After
作用:声明方法为后置通知方法
使用:在后置通知方法上声明
注意:需要在其中声明对应的切点的全限定路径
⑦ @Around
作用:声明方法为环绕通知方法
使用:在环绕通知方法上声明
注意:需要在其中声明对应的切点的全限定路径
⑧ @AfterThrowing
作用:声明方法为异常通知方法
使用:在异常通知方法上声明
注意:需要在其中声明对应的切点的全限定路径
注意:
需要在Spring的配置文件中声明AOP注解生效