您的位置:首页 > 编程语言 > Java开发

Spring的AOP思想的全面讲解(包含概念、注解和xml两种方式的实现)_chenjie的博客

2020-08-12 15:52 1101 查看

一、Spring的AOP

AOP的思想:是Aspect oritention programming面想切面编程的简写。把一个个横切关注点(零散存在于业务方法中的功能代码)放进某一个模块中去,我们称这个模块为一个切面。每一个切面都能影响业务的某一个功能,切面的目的就是为了增强。

AOP的目的:AOP能将与业务无关、但是又为业务模块所共同调用的逻辑或其他内容进行封装;减少代码重复率,降低模块之间的耦合度,提高后期的可维护性。

AOP的优势:降低模块的耦合度、让系统更容易扩展、提高后期可维护度。换句话说就是,把多个方法前后相同的代码抽取出来,使用动态代理的方式来控制。运行的时候,先执行抽取出来的方法,再执行真实的方法。

AOP中的一些概念
Joinpoint:连接点,被拦截到需要被增强的方法。where:去哪里做增强
Pointcut:切入点,哪些包中的哪些类中的哪些方法,可认为是连接点的集合。where:去哪些地方做增强
Advice:增强,当拦截到Joinpoint之后,在方法执行的什么时机(when)做什么样(what)的增强。
Aspect:切面,Pointcut+Advice,去哪些地方+在什么时候+做什么增强
Weaving:织入,把Advice加到Target上之后,创建出Proxy对象的过程。

使用AOP之前,下面三中方法中(权限控制、日志控制、事务控制),存在大量的代码冗余,不利于后期维护。

使用AOP之后,抽取共同的代码部分(权限控制、日志控制、事务控制),需要使用的时候再插入,可大大降低重复代码量,提高后期的可维护性。

二、PointCut语法

PointCut语法的作用,就是为了表达在哪些方法上,使用哪些方法对它进行增强。

AspectJ切入点语法如下
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

翻译成中文
execution(<访问修饰符>? <返回类型> <声明类型>? <方法名>(<参数>) <异常>?)

?:表示可以出现一次,或者不出现.没有问号,表示必须出现一次.
通配符:
*:匹配任何部分,只能表示一个单词
…: 可用于全限定名中和方法参数中,分别表示子包和0到N个参数

举例:
1、表示所有的public方法

execution(public * *(..))

2、表示所有以set开头方法

execution(* set*(..))

3、表示所有由method接口定义的任何方法

execution(* com.xyz.service.method*(..))

4、表示所有在service包下的方法

execution(* com.xyz.service.*.*(..))

5、表示所有在service包下,包括其子包中的方法

execution(* com.xyz.service..*.*(..))

三、使用xml方式实现AOP

1、导入依赖包

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
</dependencies>

2、创建包、类,目录结构如下:

3、各个类中方法的撰写
Transaction类(需要被增强的类),里面包含两个方法,一个能正常执行的insert()方法,一个主动抛出异常的delete()方法。

public class Transaction {

public void insert(){
System.out.println("插入数据!!!");
}

public void delete(){
System.out.println("删除数据!!!");
System.out.println(1/0);
}
}

TransactionManager类(使用里面的方法,去增强其他的类),里面包含四个方法,在不同时期对需要被增强的方法进行增强。

public class TransactionManager {

public void before(){
System.out.println("before前置增强!");
}

public void afterReturning(){
System.out.println("afterReturning后置增强!");
}

public void throwing(){
System.out.println("throwing异常增强!");
}

public void after(){
System.out.println("after最终增强!");
}
}

applicationContext.xml文件

<!--把这两个类交给spring管理    -->
<bean id="transaction" class="com.springaop.service.Transaction"></bean>
<bean id="transactionManager" class="com.springaop.tx.TransactionManager"></bean>

<!--AOP配置    -->
<aop:config>
<!--表示哪里的方法需要进行增强-->
<aop:pointcut id="txPointCut" expression="execution(* com.springaop.service.*.*(..))"/>
<!--增强的方法从哪个类中获取-->
<aop:aspect ref="transactionManager">
<!--四种增强方法-->
<aop:before method="before" pointcut-ref="txPointCut"/>
<aop:after-returning method="afterReturning" pointcut-ref="txPointCut"/>
<aop:after-throwing method="throwing" pointcut-ref="txPointCut"/>
<aop:after method="after" pointcut-ref="txPointCut"/>
</aop:aspect>
</aop:config>

TransactionTest测试类

//使用spring的测试方式
@RunWith(SpringJUnit4ClassRunner.class)
//导入spring配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class TransactionTest {

@Autowired
private ApplicationContext context;

@Test
public void test1(){
Transaction transaction = context.getBean(Transaction.class);
transaction.insert();
}

@Test
public void test2(){
Transaction transaction = context.getBean(Transaction.class);
transaction.delete();
}
}

运行结果:
1、test1()方法的执行结果如下,可以看到该方法正常执行,增强方法也执行了。

2.test2()方法的执行结果如下,可以看到,我们主动编写的除零异常产生了,于是执行了异常增强方法。

四、使用注解方式实现AOP

1、导入依赖包
同上
2、创建类和包
同上
3、各个类中方法的撰写
Transaction类:同上

TransactionManager类(类上贴上Aspect注解,每个方法都贴上对应增强时期的注解)

@Aspect
public class TransactionManager {

@Before("execution(* com.springaop.service.Transaction.*(..))")
public void before(){
System.out.println("before前置增强!");
}

@AfterReturning("execution(* com.springaop.service.Transaction.*(..))")
public void afterReturning(){
System.out.println("afterReturning后置增强!");
}

@AfterThrowing("execution(* com.springaop.service.Transaction.*(..))")
public void throwing(){
System.out.println("throwing异常增强!");
}

@After("execution(* com.springaop.service.Transaction.*(..))")
public void after(){
System.out.println("after最终增强!");
}
}

applicationContext.xml文件,开启AOP注解扫描即可

<!--把这两个类交给spring管理    -->
<bean id="transaction" class="com.springaop.service.Transaction"></bean>
<bean id="transactionManager" class="com.springaop.tx.TransactionManager"></bean>

<!--AOP注解扫描    -->
<aop:aspectj-autoproxy/>

TransactionTest测试类,同上

运行结果:
1、test1()方法的执行结果如下,正常执行。

2.test2()方法的执行结果如下,达到预期效果。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: