一、概念
AspectJ是一个基于java语言的AOP框架,扩展了java语言,提供了强大的AOP功能。
使用AspectJ需要jar包:Aspectjrt.jar、Aspectjweaver.jar、Aspectj.jar
下载地址:https://www.eclipse.org/aspectj/downloads.php
使用方式:
- 基于XML声明式AspectJ
- 基于Annotation的声明式AspectJ
二、基于AspectJ XML开发
所有的切面都需要定义在aop:config元素中:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
</beans>
2.1、定义切面aop:aspect
该元素可以将定义好的Bean转换为切面Bean,所以使用aop:aspect需要定义一个普通的SpringBean。
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<bean id="test" class="com.jsonliu.bean.Test"/>
<aop:config>
<aop:aspect id="myAspect" ref="test">
</aop:aspect>
</aop:config>
</beans>
2.2、定义切入点aop:pointcut
aop:pointcut用来定义一个切入点,当aop:pointcut元素作为aop:config元素的子元素定义时,表示该切入点是全局切入点,它可以被多个切面共享;当aop:pointcut元素作为aop:aspect元素的子元素定义时,表示该切入点只对当前切面有效。
<aop:config>
<aop:pointcut id="myPointCut" expression="execution(* com.jsonliu.service.*.*(..))"/>
</aop:config>
id表示切入点唯一标识名称,execution用于指定切入点关联的切入点关系。
2.3、excution表达式
execution(modifiers-pattern returning-type-pattern declaring-type-pattern name-pattern(param-pattern)throws-pattern)
return-type-pattern、name-pattern、param-pattern必须,其他可选。
注意:return-type-pattern、name-pattern表达式之前有空格
参数 | 说明 |
---|---|
modifiers-pattern | 修饰符:private、public |
returning-type-pattern | 返回值类型,*表示可以为任何返回值,如果返回值为对象,则需要指定全路径类名。 |
declaring-type-pattern | 指定方法的包名。 |
name-pattern | 指定方法名,代表所,set代表以set开头的所有方法。 |
param-pattern | 指定方法的参数(声明的类型,(…)代表所有从那时速,(.)代表一个参数,(.,String)代表第一个参数为任何值,第二参数是String类型) |
throws-pattern | 指定抛出的异常类型 |
2.4、实例
public class Logging {
public void beforeAdvice(){
System.out.println("前置通知");
}
public void afterAdvice(){
System.out.println("后置通知");
}
public void afterReturningAdvice(Object retVal){
System.out.println("返回值为:"+retVal.toString());
}
public void afterThrowingAdvice(IllegalArgumentException ex){
System.out.println("异常信息:"+ex.toString());
}
}
public class Man {
private String name;
private Integer age;
public Man() {
System.out.println("Man的无参构造函数");
}
public Man(String name, Integer age) {
System.out.println("Man的有参构造函数");
this.name = name;
this.age = age;
}
public void show(){
System.out.println("名称:"+name+",年龄:"+age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void throwException(){
System.out.println("Man抛出异常");
throw new IllegalArgumentException();
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<bean id="man" class="com.jsonliu.bean.Man">
<property name="name" value="天下"/>
<property name="age" value="1000" />
</bean>
<bean id="logging" class="com.jsonliu.aspect.Logging"/>
<aop:config>
<aop:aspect id="logs" ref="logging">
<aop:pointcut id="selectAll" expression="execution(* com.jsonliu.bean.*.*(..))"/>
<!-- 前置通知 -->
<aop:before pointcut-ref="selectAll" method="beforeAdvice"/>
<!-- 后置通知 -->
<aop:after-returning pointcut-ref="selectAll" method="afterReturningAdvice" returning="retVal"/>
<!-- 异常通知 -->
<aop:after-throwing pointcut-ref="selectAll" method="afterThrowingAdvice" throwing="ex" />
<!-- 最终通知 -->
<aop:after pointcut-ref="selectAll" method="afterAdvice" />
</aop:aspect>
</aop:config>
</beans>
public class TestAop {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("AspectBeans.xml");
Man man = (Man) context.getBean("man");
man.getName();
man.getAge();
man.throwException();
}
}
执行结果:
三、基于AspectJ注解开发
3.1、概念
AspectJ框架为AOP开发提供了一套注解,允许使用注解定义切面、切入点和增强处理,Spring框架可以根据这些注解生成AOP代理。
名称 | 说明 |
---|---|
@Aspect | 用于定义一个切面 |
@Pointcut | 用于定义一个切入点 |
@Before | 用于定义前置通知,相当于BeforeAdvice |
@AfterReturning | 用于定义后置通知,相当于AfterReturningAdvice |
@Around | 用于定义环绕通知,相当于MethodInterceptor |
@AfterThrowing | 用于定义抛出通知,相当于ThrowAdvice |
@After | 用于定义最终final通知,不管是否异常,该同志都会执行。 |
@DeclareParents | 用于定义引介通知,相当于IntroductionInterceptor |
3.2、启用
1、使用@Configuration和@EnableAspectJAutoProxy
@Configuration
@EnableAspectJAutoProxy
public class Appconfig{}
2、基于XML配置
<aop:aspectj-autoproxy>
3.3、定义切面@Aspect
AspectJ类和其他普通的Bean一样,可以有方法和字段,不同的是AspectJ类需要@Aspect注解
@Aspect
public class AspectModule{}
Aspect类也可以像其他Bean一样在XML中配置
<bean id="myAspect" class="com.jsonliu.AspectModule" />
3.4、定义切入点
@Pointcut需要一个切入点
@Pointcut("execution(* com.jsonliu..*.*(..))")
private void myPointCut(){}
XML中配置:
<aop:pointcut expression="execution(* com.jsonliu..*.*(..))" id="myPointCut" />
3.5、定义通知advice
@Aspect支持5中类型advice,例如:
@Before("myPointCut()")
public void beforeAdvice(){}
3.6、实例
@Aspect
public class Logging {
@Pointcut("execution(* com.jsonliu.bean.*.*(..))")
private void selectAll(){}
@Before("selectAll()")
public void beforeAdvice(){
System.out.println("前置通知");
}
@After("selectAll()")
public void afterAdvice(){
System.out.println("后置通知");
}
@AfterReturning(pointcut = "selectAll()",returning = "retVal")
public void afterReturningAdvice(Object retVal){
System.out.println("返回值为:"+retVal.toString());
}
@AfterThrowing(pointcut = "selectAll()",throwing = "ex")
public void afterThrowingAdvice(IllegalArgumentException ex){
System.out.println("异常信息:"+ex.toString());
}
}
public class Man {
private String name;
private Integer age;
public Man() {
System.out.println("Man的无参构造函数");
}
public Man(String name, Integer age) {
System.out.println("Man的有参构造函数");
this.name = name;
this.age = age;
}
public void show(){
System.out.println("名称:"+name+",年龄:"+age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void throwException(){
System.out.println("Man抛出异常");
throw new IllegalArgumentException();
}
}
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<aop:aspectj-autoproxy />
<bean id="logging" class="com.jsonliu.aspect.Logging"/>
<bean id="man" class="com.jsonliu.bean.Man">
<property name="name" value="天下"/>
<property name="age" value="1000" />
</bean>
</beans>
public class TestAop {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("AspectBeans1.xml");
Man man = (Man) context.getBean("man");
man.getName();
man.getAge();
man.throwException();
}
}
运行结果: