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

spring03_03_[掌握]Spring中AOP使用(含源码下载)基于XML、注解的AOP配置

2019-04-06 17:26 471 查看

先上代码:项目源码下载(软件:IDEA):

基于XML的AOP配置

链接:https://pan.baidu.com/s/1wSbq5jYeykOxTUmjEvmz5A 
提取码:9sox 

基于注解的AOP配置

链接:https://pan.baidu.com/s/17QO6XzA5UGPHcW8JBrcHeg 
提取码:tw1g 

AOP相关术语

  1. Joinpoint(连接点)

横切程序执行的特定位置,比如类开始初始化前,类初始化之后,类中某个方法调用前、调用后,方法抛出异常后等,这些代码中的特定点就称为“连接点”。

Spring仅支持方法的连接点,即仅能在方法调用前、方法调用后、方法抛出异常时以及方法调用前后这些程序执行点织入增强。

我们知道黑客攻击系统需要找到突破口,没有突破口就无法进行攻击,从这一角度上来说,AOP是一个黑客(因为它要向目前类中嵌入额外的代码逻辑),连接点就是AOP向目标类打入楔子的候选点。

    2.Pointcut(切入点)

一个类中可以有很多个方法,每个方法又有多个Joinpoint,在这么多个方法中,如何定位到自己感兴趣的方法呢?靠的是切点

注意:切点只定位到某个方法上,所以如果希望定位到具体连接点上,还需要提供方位信息  

比如:如果把一个方法理解成数据表中的一条记录的话,那么切入点就好比你select语句的where条件 ,就可以定位到你感兴趣的方法

    3.Advice(通知/增强)

增强的第一层意思就是你的横切逻辑代码(增强逻辑代码)

在Spring中,增强除了用于描述横切逻辑外,包含一层意思就是横切逻辑执行的方位信息。刚刚说了切点只能定位到方法,在进一步使用方位信息就可以定位到我们感兴趣的连接点了(方法调用前、方法调用后还是方法抛出异常时等)。  

    4.Target(目标对象)

增强逻辑的织入目标类。比如未添加任何事务控制的AccountServiceImplNoTcf类  

    5.Weaving(织入)

织入是将增强逻辑/横切逻辑添加到目标类具体连接点上的过程,AOP像一台织布机,将目标类、增强或者引介通过AOP(其实就是动态代理技术)这台织布机天衣无缝地编织到一起。

Spring采用动态代理织入。  

    6.Proxy(代理)

一个类被AOP织入增强后,就产出了一个结果类,它是融合了原类和增强逻辑的代理类。  

    7.Aspect(切面)

切面由切点和增强(引介)组成。

切面=切点+增强

       =切点+方位信息+横切逻辑

       =连接点+横切逻辑

最终切面完成:把横切逻辑织入到哪些方法的方法前/后等

本质:把横切逻辑增强到连接点(切点和方位信息都是为了确定连接点)上

Spring关于JDK/CGLIB动态代理的选择

Spring发现涉及到接口那就使用JDK动态代理,如果不涉及接口就使用CGLIB动态代理

AOP:日志、性能监控、事务、权限控制

基于XML的AOP配置

    需求:在Service层代码的不同方法的不同连接点JoinPoint织入日志

把Account表的service层进行crud模拟(dao层就不需要了)

    引入POM坐标

[code]<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>

applicationContext.xml配置

 <aop:config> 所有aop配置的根标签
<aop:aspect id="logAspect" ref="log"> 配置切面对象,id自定义,ref横切逻辑类的bean标签id值
<aop:pointcut> 配置切入点
   属性值:id自定义
   属性值:expression 匹配方法的表达式
<aop:before> 被切入的方法前执行
   属性method:printBeforeMethod切入的方法名
   属性pointcut-ref:切入点标签的id属性值

[code]<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.itheima"></context:component-scan>

<!-- 横切逻辑配置-->
<bean id="log" class="com.itheima.utils.LogUtil">

</bean>
<!-- 配置aop的根标签-->
<aop:config>
<!-- 切面配置-->
<aop:aspect id="logAspect" ref="log">
<!--
配置切入点
before:方法执行之前
method:切入的方法名
pointcut:感兴趣的方法,被切入的方法

-->
<!--<aop:before method="printBeforeMethod"
pointcut="execution( int com.itheima.service.AccountService.saveAccount(com.itheima.pojo.Account))"></aop:before>-->
<!--
表达式配置
方法参数:* 匹配任意参数,必须有参数
.. 匹配任意参数,有无参数均可
方法名:*
返回值:*
-->
<aop:pointcut id="point1" expression="execution( * com.itheima.service.AccountService.*(..))"></aop:pointcut>
<aop:before method="printBeforeMethod" pointcut-ref="point1"></aop:before>
<aop:after-returning method="pringAfterReturn" pointcut-ref="point1"></aop:after-returning>
<aop:after-throwing method="printAfterThrowing" pointcut-ref="point1"></aop:after-throwing>
<aop:after method="printAfterMethod" pointcut-ref="point1"></aop:after>
</aop:aspect>
</aop:config>

</beans>

日志对象:横切逻辑

[code]public class LogUtil {
//方法执行之前
public void printBeforeMethod(){
System.out.println("方法之前执行");
}

//方法执行之后打印
public void printAfterMethod(){
System.out.println("方法执行之后");
}

//方法异常执行打印
public void printAfterThrowing(){
System.out.println("方法异常时");
}

//方法正常执行打印
public void pringAfterReturn(){
System.out.println("方法正常时");
}
}

service层

[code]@Service("accountServiceImpl")
public class AccountServiceImpl implements AccountService {

public int saveAccount(Account account) {
System.out.println("模拟保存账户");
return 0;
}

@Override
public int updateAccountById(Account account) {
System.out.println("模拟更新账户");
return 0;
}

@Override
public int deleteAccountById(int id) {
System.out.println("模拟删除账户");
return 0;
}

@Override
public Account queryAccountById(int id) {
System.out.println("模拟查询账户");
return null;
}
}

测试类

[code]@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MainTest {

@Autowired
@Qualifier("accountServiceImpl")
private AccountService accountService;

@Test
public void testAop(){
accountService.saveAccount(new Account());
// accountService.queryAccountById(1);
}
}

环绕通知

它是spring为我们提供的一种可以在代码中手动控制增强方法何时执行的方式,灵活度比较高,设置可以控制原业务逻辑是否执行。

注意:通常情况下,环绕通知都是独立使用的,不要和上面的四种通知类型混合使用

   <aop:around method="printRound" pointcut-ref="point1"></aop:around> 环绕通知配置
 ProceedingJoinPoint进程切入点对象,执行我们的业务逻辑方法
   方法:proceed() 执行我们自己的业务逻辑方法


 applicationContext.xml配置

[code]<aop:around method="printRound" pointcut-ref="point1"></aop:around>

日志对象:横切逻辑

[code]//环绕通知
public Object printRound(ProceedingJoinPoint proceedingJoinPoint){
Object result = null;
try{
System.out.println("方法前执行");
result = proceedingJoinPoint.proceed();
System.out.println("方法正常执行");
}catch (Throwable ex){
ex.printStackTrace();
System.out.println("方法异常执行");
}
System.out.println("方法后执行");
return result;
}

基于注解的AOP配置

创建框架启动配置类

[code]@Component
@ComponentScan("com.itheima")
//启用动态代理
@EnableAspectJAutoProxy
public class SpringConfig {
}

测试类

[code]@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class MainTest {

@Autowired
@Qualifier("accountServiceImpl")
private AccountService accountService;

@Test
public void testAop(){
accountService.saveAccount( new Account());
}

}

学习spring中的AOP时要明确的事

  1. AOP的使用场景

AOP的应用场景往往是受限的,它一般只适合于那些具有横切逻辑的应用场合:如性能监测、访问控制、事务管理以及日志记录等。不过,这丝毫不影响AOP作为一种新的软件开发思想在软件开发领域所占有的地位。

    2.开发阶段(我们完成)

        编写核心业务代码

        大部分程序员来做,要求熟悉业务需求。

        抽取公用代码制作成通知,进行AOP配置

        一般由专门的AOP编程人员来做

    3.运行阶段(Sprin 1c140 g框架完成)

    Spring框架监控切入点方法的执行。一旦监控到切入点方法被运行,Spring框架使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。

 

 

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