AspenctJ简介:
AspectJ是基于Java语言的AOP框架(是一个单独的框架)
Spring2.0之后提供对AspectJ的切点表达式的支持
@AspectJ通过JDK5注解技术允许直接在bean类中定义切面
建议用AspectJ进行开发
在代码开始之前我们要进行环境准备
1、创建工程,传送门
2、引入jar包
也就是配置Pom文件,通过maven仓库引入依赖
内容如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jjyu</groupId>
<artifactId>Spring_aspect</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Spring_aspect Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--引入Spring的基本开发包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>Spring_aspect</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
3、配置xml文件
4、开启AspectJ的注解开发,自动代理
3和4我们在下面的代码中再说,目前还是先建好项目结构便好。
–注解方式
@AspectJ提供不同的通知类型
@Before前置通知,相当于BeforeAdvice,在操作之前进行增强,可以在方法中传入JoinPoint对象,用来获得切点信息
@AfterReturning后置通知,相当于AfterReturningAdvice,通过returning属性可以定义方法返回值,作为参数
@Around环绕通知,相当于MethodInterceptoraround方法的返回值就是目标代理方法执行的返回值,参数为ProceedingJoinPoint可以调用拦截目标方法执行,如果不调用ProceedingJointPoint的proceed方法,那么目标方法就被拦截了,也就是不会被执行
@AfterThrowing异常抛出通知,相当于ThrowAdvice,设置throwing属性可以设置发生异常对象参数
@After最终final通知,不管是否异常,该通知都会执行
@DeclareParents引介通知,相当于IntroductionInterceptor
通过@PointCut为切点命名,在每个通知内定义切点,会造成工作量大,不易维护,对于重复的切点,可以使用@PointCut进行定义,切点方法:private void无参数方法,方法名为切点名有多个切点时,使用||进行连接
在通知中通过Value属性定义切点
通过execution函数,可以定义切点方法切入
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
匹配所有类public方法 execution(public * * (…))
匹配指定包下所有类方法execution(* com.imooc.* (…))不包含子包execution(* com.imooc…* (…))包含子包所有类
匹配指定类所有方法 execution(* com.imooc.service.* (…))
匹配实现特定接口所有类方法 execution(* com.imooc.dao+.(…))
匹配所有save开头的方法execution( save*(…))
首先开始demo1
我们编写MyAspectAnno类和ProductDao类
/**
* 切面类
*/
@Aspect
public class MyAspectAnno {
@Before(value = "myPointCut1()")
public void before(JoinPoint joinPoint){
System.out.println("前置通知------"+joinPoint);
}
// @AfterReturning(value = "execution(* com.jjyu.aspectj.demo1.ProductDao.update(..))",returning = "result")
@AfterReturning(value = "myPointCut2()",returning = "result")
public void afterReturning(Object result){
System.out.println("后置通知---------"+result);
}
@Around(value = "myPointCut3()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前-----通知");
//执行了目标方法
Object obj=joinPoint.proceed();
System.out.println("环绕后------通知");
return obj;
}
@AfterThrowing(value = "myPointCut5()",throwing = "e")
public void afterThrowing(Throwable e){
System.out.println("异常抛出通知----------"+e);
}
@After(value = "myPointCut4()")
public void after(){
System.out.println(" 最终通知----------");
}
// @Pointcut(value = "execution(* com.jjyu.aspectj.demo1.ProductDao.save(..))")
@Pointcut(value = "execution(* com.jjyu.aspectj.demo1.ProductDao.save(..))")
private void myPointCut1(){
}
@Pointcut(value = "execution(* com.jjyu.aspectj.demo1.ProductDao.update(..))")
private void myPointCut2(){
}
@Pointcut(value = "execution(* com.jjyu.aspectj.demo1.ProductDao.delete(..))")
private void myPointCut3(){
}
@Pointcut(value = "execution(* com.jjyu.aspectj.demo1.ProductDao.findAll(..))")
private void myPointCut4(){
}
@Pointcut(value = "execution(* com.jjyu.aspectj.demo1.ProductDao.findOne(..))")
private void myPointCut5(){
}
}
public class ProductDao {
public void save(){
System.out.println("save ....");
}
public void delete(){
System.out.println("delete ....");
}
public String update(){
System.out.println("update ....");
return "hello afterReturning";
}
public void findOne(){
System.out.println("findOne ....");
// int k=1/0;
}
public void findAll(){
System.out.println("findAll ....");
}
}
<?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">
<!--开启AspectJ的注解开发,自动代理-->
<aop:aspectj-autoproxy/>
<!--目标类-->
<bean id="productDao" class="com.jjyu.aspectj.demo1.ProductDao"/>
<!--定义切面-->
<bean class="com.jjyu.aspectj.demo1.MyAspectAnno"/>
</beans>
对应测试类和效果
/*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo1 {
@Resource(name = "productDao")
private ProductDao productDao;
@Test
public void demo1(){
productDao.save();
System.out.println();
productDao.delete();
System.out.println();
productDao.findAll();
System.out.println();
productDao.findOne();
System.out.println();
productDao.update();
}
}
–XML方式
使用XML配置切面
在demo2中
我们的CustomerDao接口和其实现类以及MyAspectXML类的详细代码
public interface CustomerDao {
public void save();
public void delete();
public void findOne();
public void findAll();
public String updata();
}
public class CustomerDaoImpl implements CustomerDao {
@Override
public void save() {
System.out.println("save====");
}
@Override
public void delete() {
System.out.println("delete====");
}
@Override
public void findOne() {
System.out.println("findOne====");
int k=1/0;
}
@Override
public void findAll() {
System.out.println("findAll====");
// int k=1/0;
}
@Override
public String updata() {
System.out.println("uodate====");
return "update+after";
}
}
public class MyAspectXml {
//前置通知
public void before(JoinPoint joinPoint){
System.out.println("xml --- before----------"+joinPoint);
}
//后置通知
public void afterReturning(Object result){
System.out.println("xml----afterreturning-----"+result);
}
//环绕通知
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("XML环绕前通知-------");
Object obj= joinPoint.proceed();
System.out.println("XML环绕后通知-----");
return obj;
}
//异常抛出通知
public void afterThrowing(Throwable e){
System.out.println("XML方式的异常抛出通知----"+e);
}
//最终通知
public void after(){
System.out.println("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: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">
<!--使用XML配置方式完成AOP的开发-->
<!--配置目标类-->
<bean id="customerDao" class="com.jjyu.aspectj.demo2.CustomerDaoImpl"/>
<!--配置切面类和切面类中方法-->
<bean id="myAspectXml" class="com.jjyu.aspectj.demo2.MyAspectXml"/>
<!--aop相关配置-->
<aop:config >
<!--配置AOP的切面,和切入点-->
<aop:pointcut id="pointcut1" expression="execution(* com.jjyu.aspectj.demo2.CustomerDao.save(..))"/>
<aop:pointcut id="pointcut2" expression="execution(* com.jjyu.aspectj.demo2.CustomerDao.updata(..))"/>
<aop:pointcut id="pointcut3" expression="execution(* com.jjyu.aspectj.demo2.CustomerDao.delete(..))"/>
<aop:pointcut id="pointcut4" expression="execution(* com.jjyu.aspectj.demo2.CustomerDao.findOne(..))"/>
<aop:pointcut id="pointcut5" expression="execution(* com.jjyu.aspectj.demo2.CustomerDao.findAll(..))"/>
<aop:aspect ref="myAspectXml">
<!--配置前置通知-->
<aop:before method="before" pointcut-ref="pointcut1"/>
<!--配置后置通知-->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut2" returning="result"/>
<!--配置环绕通知-->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!--配置异常抛出通知-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e"/>
<!--配置最终通知-->
<aop:after method="after" pointcut-ref="pointcut5"/>
</aop:aspect>
</aop:config>
</beans>
对应测试类以及效果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext2.xml")
public class SpringDemo2 {
@Resource(name = "customerDao")
private CustomerDao customerDao;
@Test
public void demo1() {
customerDao.delete();
customerDao.findAll();
customerDao.findOne();
customerDao.save();
customerDao.updata();
}
}