spring(5)

1. aop

      大家想象,有这样的一个情景,演员表演,观众鼓掌的情景,在表演开始之前,观众安静,在演员表演之后,鼓掌叫好,在演出失败的时候观众鼓励演员。
在生活中是这样,在程序中也有这样的情况,比如在JDBC访问数据库的时候,事务的提交总是很繁琐,一段很长很长的代码中,只有一点点的关于业务的,剩下的很多的代码都是关于数据库的访问的 比如下面的代码:
在这里插入图片描述
在每次之后都要自己手动的提交事务,在开始之前都要自己手动的开启事务,这样的列子很多,再比如,在一个系统中,我要记录操作,就是什么人在什么时候干了什么事情,那我就要在这个人操作以后,也就是对应的service层的方法执行之后要记录,如果每次都在业务层的方法中调用记录操作的方法,就很多余。
也就是在程序中有很多的交叉事务 如下图所示
在这里插入图片描述
会有很多的交叉事务,比如安全,事务,和一些其他的交叉事务贯穿在程序中的每个层面。为了解决这个问题,就引出了aop,面向切面编程,将一些交叉事务提取出来,将它引入到 需要的地方,就很好的解决了这个问题,主业务逻辑只关注自己的事情,并不需要关注其他的事情。

2. aop的专业名词

aop全称为(Aspect Oriented Programming) 详细请看 aop-百度百科
在aop中很一些专业名词,需要了解一下

  • 通知(advice)
    就是之前所讲的交叉事务,比如之前所讲的演员和观众的问题,观众的表演之前的安静,表演之后的鼓掌,表演失败之后的鼓励演员,就是通知,观众的这几个动作放到同一个类中,这个类就是通知类。 正规的解释就是 切面的工作叫做通知,虽然我不怎么喜欢这个解释,简单的讲,就是定义了切面要干啥事。
  • 切点(point cut)
    就是定义了通知类中的方法要作用到哪些方法上。上面的例子中,也就是观众的安静这个动作要作用到哪些方法上,显而易见,是作用在观众表演之前的方法上。 通知是定义要干什么,切点就是定义了去哪里干
  • 连接点 (joint point)
    这个不太好说,要是不太理解,到最后的程序中就能理解了,
    连接点就是程序中潜在的对象,也就是程序宏所有方法都可能是连接点,
  • 切面(Aspect)
    通知 + 切点 = 切面
  • 织入(weaving)
    织入就是把切面应用到目标对象并且创建代理对象的过程。
    在织入的过程中有三种方式:
  • 编译期: 顾名思义,就是在目标类的编译期时候织入,这种方法需要特殊的编译器。AspectJ的织入就是这种
  • 类加载期: 目标类被加载到JVM的时候织入,这种方法需要特殊的类加载器(classloader),在目标类在应用之前增强它的字节码。AspectJ5就这种
  • 运行期: 在运行的时候织入,Aop容器会自动创建一个代理对象。AOP就是这种

实现动态代理的方式有两种

  • 如果目标类没有实现任何的接口,cglib 字节码增强
  • 如果实现了接口,JDK动态代理

在这里插入图片描述

在这里插入图片描述

3.一个aop的例子

将上面的例子实例化
aop的实现也有两种方式,一种是xml,一种是注解
在这里会结合之前的内容
步骤:

  1. 创建一个表演的接口
  2. 创建一个演员类实现表演接口
  3. 创建一个舞台类
  4. 在舞台类中注入一个演员
  5. 在舞台类中调用演员表演
  6. 创建一个观众的通知类
  7. 将通知类中的方法织入到舞台类中。
    看代码
  • xml

创建一个表演的接口
package second;

public interface Performance {
    public void dance();
}


-----------------------------------------------------------------------------
 创建一个演员类实现表演接口
 package second;

import org.springframework.stereotype.Component;

@Component
public class Actor  implements  Performance{

    public void dance() {
        System.out.println("Actor.dance");
    }
}

-----------------------------------------------------------------------------
创建一个舞台类
package second;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Stage {

    @Autowired
    private Performance actor;

    public void actorPerformance(){
        actor.dance();
    }


}
-----------------------------------------------------------------------------
创建一个观众的通知类
package second;

public class AudienceAdvice {


    public void quite(){
        System.out.println("安静");
    }

    public void applause(){
        System.out.println("鼓掌");
    }

    public void refuel(){
        System.out.println("你可以 加油!!!");
    }

}

-----------------------------------------------------------------------------

配置文件(applicationContext.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:context="http://www.springframework.org/schema/cache"
       xmlns:contex="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/cache http://www.springframework.org/schema/cache/spring-cache.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">


<!---
	注意:
		所有的关于切面的配置都以 aop开头的
----->
    <contex:component-scan base-package="second"/>
    
    <bean id="advice" class="second.AudienceAdvice"></bean>
    
    <aop:config>
        	/*
        		定义切点  
        		expression 定义的是切点表达式 具体的语法在后面会有介绍
			*/
        <aop:pointcut id="pointcut" expression="execution(public * second.Stage.actorPerformance())"/>

        <aop:aspect id="aspect" ref="advice">
        	/*
        		在目标方法之前调用

        	*/
            <aop:before method="quite" pointcut-ref="pointcut"></aop:before>
			/*
        		在目标方法之后调用

        	*/
            <aop:after method="applause" pointcut-ref="pointcut"/>
			/*
        		在目标方法出错之后调用
        	*/
            <aop:after-throwing method="refuel" pointcut-ref="pointcut"/>


        </aop:aspect>

    </aop:config>


</beans>
  • 注解
    注解版和xml的差异就是 关于aop的配置在advice类中就写好了 那在这里就把 观众的advice类重写一下就好了,其他的不变
package second;


import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect //表示是一个通知类 
@Component //表示是一个组件 
public class AudienceAdvice {
    /*
        切点的复用,这里定义切点,将切点变为方法,这样就可以通过类名.方法名来复用切点 ,要是在自己的类中
        就不需要类名
     */
    @Pointcut("execution(public * second.Stage.actorPerformance())")
    public void pointcut1(){}

    @Before("AudienceAdvice.pointcut1()")
    public void quite(){
        System.out.println("安静");
    }

    @After("AudienceAdvice.pointcut1()")
    public void applause(){
        System.out.println("鼓掌");
    }

    @AfterThrowing("AudienceAdvice.pointcut1()")
    public void refuel(){
        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:context="http://www.springframework.org/schema/cache"
       xmlns:contex="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/cache http://www.springframework.org/schema/cache/spring-cache.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">



    <contex:component-scan base-package="second"/>

	<!----
		这个表示自动创建代理
	------>
    <aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
 </beans>

结果:

在这里插入图片描述

4.补充说明

  • 通知的分类
    通知分为下面几个类别
  • 切入点表达式在这里插入图片描述
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值