JAVA框架学习文章点这里
AspectJ:
AspectJ是一个基于Java语言的AOP框架
Spring2.0以后新增了对AspectJ切点表达式支持
@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP
主要用途:自定义开发
切入点表达式:
1.execution:用于描述方法
2.within:匹配包或子包中的方法
3.this:匹配实现接口的代理对象中的方法
4.target:匹配实现接口的目标对象中的方法
5.args:匹配参数格式符合标准的方法
6.bean(id) 对指定的bean所有的方法
主要使用的还是execution,以下举一个例子
execution(* com.h_Aspectj_xml.BookServiceImpl.*(..))
表示指定 返回值任意类型,在指定类中的任意方法(方法参数为任意类型)
AspectJ通知类型:
before:前置通知(应用:各种校验),在方法执行前执行,如果通知抛出异常,阻止方法运行
afterReturning:后置通知(应用:常规数据处理),方法正常返回后执行,如果方法中抛出异常,通知无法执行,必须在方法执行后才执行,所以可以获得方法的返回值。
around:环绕通知(应用:可以做任何事情),方法执行前后分别执行,可以阻止方法的执行,必须手动执行目标方法
afterThrowing:抛出异常通知(应用:包装异常信息),方法抛出异常后执行,如果方法没有抛出异常,无法执行,after:最终通知(应用:清理现场),方法执行完毕后执行,无论方法中是否出现异常
基于xml的使用:
before(前置方法)的使用:
目标类:
public interface BookService {
public void addBook();
public void deleteBook();
public void selectBook();
}
package com.h_Aspectj_xml;
public class BookServiceImpl implements BookService{
public void addBook() {
System.out.println("add books");
}
public void deleteBook() {
System.out.println("delete books");
}
public void selectBook() {
System.out.println("select books");
}
}
切面类:
package com.h_Aspectj_xml;
import org.aspectj.lang.JoinPoint;
public class MyAspect{
public void myBefore(JoinPoint joinPoint) {
System.out.println("before:"+joinPoint.getSignature().getName());
}
}
配置文件:
<?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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean name="BookService" class="com.h_Aspectj_xml.BookServiceImpl"></bean>
<bean name="MyAspect" class="com.h_Aspectj_xml.MyAspect"></bean>
<aop:config>
<!--配置切入点类-->
<aop:pointcut expression="execution(* com.h_Aspectj_xml.BookServiceImpl.*(..))" id="myCutPoint"/>
<!--配置切面,以及before使用的方法和切入点-->
<aop:aspect ref="MyAspect">
<aop:before method="myBefore" pointcut-ref="myCutPoint" />
</aop:aspect>
</aop:config>
</beans>
测试类:
package com.h_Aspectj_xml;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
@Test
public void test1() {
String xmlPath = "com/h_Aspectj_xml/beans.xml";
ApplicationContext appcont = new ClassPathXmlApplicationContext(xmlPath);
BookService bookService = (BookService) appcont.getBean("BookService");
bookService.addBook();
bookService.selectBook();
bookService.deleteBook();
}
}
结果:
before:addBook
add books
before:selectBook
select books
before:deleteBook
delete books
after(后置方法)的使用:
目标类:同上
切面类:在上面的基础上加上一个方法
public void myAfterReturning(JoinPoint joinPoint, Object ret) {
System.out.println(joinPoint.getSignature().getName()+",after,返回值:"+ret);
}
配置文件
<aop:config>
<aop:pointcut expression="execution(* com.h_Aspectj_xml.BookServiceImpl.*(..))" id="myCutPoint"/>
<aop:aspect ref="MyAspect">
<!--配置后置方法的方法名,切入点和返回值名-->
<aop:after-returning method="myAfterReturning" pointcut-ref="myCutPoint" returning="ret"/>
</aop:aspect>
</aop:config>
结果:
add books
addBook,after,返回值:null
select books
selectBook,after,返回值:null
delete books
deleteBook,after,返回值:null
afterThrowing(异常处理)的使用
在前面的实现类中修改方法制造异常
public void deleteBook() {
int a = 10/0;
System.out.println("delete books");
}
在前面切面类的基础上添加方法:
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println(joinPoint.getSignature().getName()+"方法抛出异常:"+e.getMessage());
}
修改配置文件:
<aop:config>
<aop:pointcut expression="execution(* com.h_Aspectj_xml.BookServiceImpl.*(..))" id="myCutPoint"/>
<aop:aspect ref="MyAspect">
<!--指定异常处理方法名,切入点和抛出的异常对象名称-->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myCutPoint" throwing="e"/>
</aop:aspect>
</aop:config>
结果:
add books
select books
deleteBook方法抛出异常:/ by zero
around(环绕通知)的使用:
屏蔽掉之前在实现类中写的异常
在切面类中添加方法:
public void myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("前");
//环绕需要手动调用目标方法
Object object = joinPoint.proceed();
System.out.println("后");
}
修改配置文件
<aop:config>
<aop:pointcut expression="execution(* com.h_Aspectj_xml.BookServiceImpl.*(..))" id="myCutPoint"/>
<aop:aspect ref="MyAspect">
<aop:around method="myAround" pointcut-ref="myCutPoint"/>
</aop:aspect>
</aop:config>
运行结果:
前
add books
后
前
select books
后
前
delete books
后
after(最终)的使用:
在切面类中添加方法:
public void myAfter(JoinPoint joinPoint) {
System.out.println("finall");
}
修改配置文件:
<aop:config>
<aop:pointcut expression="execution(* com.h_Aspectj_xml.BookServiceImpl.*(..))" id="myCutPoint"/>
<aop:aspect ref="MyAspect">
<aop:after method="myAfter" pointcut-ref="myCutPoint"/>
</aop:aspect>
</aop:config>
运行结果:
add books
finall
select books
finall
delete books
finall
注解的使用:
目标类:
package com.h_Aspectj_anno;
import org.springframework.stereotype.Service;
@Service("BookService")
public class BookServiceImpl implements BookService{
public void addBook() {
System.out.println("add books");
}
public void deleteBook() {
//int a = 10/0;
System.out.println("delete books");
}
public void selectBook() {
System.out.println("select books");
}
}
切面类:
package com.h_Aspectj_anno;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
//配置切面类
@Component//相当于xml中配置bean
@Aspect
public class MyAspect{
//配置公共切入点,配置后可以方便后续方法引用
@Pointcut("execution(* com.h_Aspectj_anno.BookServiceImpl.*(..))")
public void myPointCut() {
}
//@Before("myPointCut()")
public void myBefore(JoinPoint joinPoint) {
System.out.println("before:"+joinPoint.getSignature().getName());
}
//@AfterReturning(value="myPointCut()" , returning="ret")
public void myAfterReturning(JoinPoint joinPoint, Object ret) {
System.out.println(joinPoint.getSignature().getName()+",after,返回值:"+ret);
}
//@AfterThrowing(value="myPointCut()", throwing="e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println(joinPoint.getSignature().getName()+"方法抛出异常:"+e.getMessage());
}
//@Around("myPointCut()")
public void myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("前");
//环绕需要手动调用目标方法
Object object = joinPoint.proceed();
System.out.println("后");
}
//@After("myPointCut()")
public void myAfter(JoinPoint joinPoint) {
System.out.println("finall");
}
}
配置文件:
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- 配置自动扫描 -->
<context:component-scan base-package="com.h_Aspectj_anno"></context:component-scan>
<!-- 配置注解自动代理 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
需要类:
package com.h_Aspectj_anno;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
@Test
public void test1() {
String xmlPath = "com/h_Aspectj_anno/beans.xml";
ApplicationContext appcont = new ClassPathXmlApplicationContext(xmlPath);
BookService bookService = (BookService) appcont.getBean("BookService");
bookService.addBook();
bookService.selectBook();
bookService.deleteBook();
}
}
需要测试那个方法就打开注解,最终效果和使用xml的时候一样