spring aop知识点整理

Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。(共有五种:before,after (无论是否发生异常,都进行执行的通知),around ,afterRunning,afterThrowing)
Target(目标对象):织入 Advice 的目标对象.。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程。
举例
需要增强的类

package aop;
 import org.springframework.stereotype.Component;
 @Component("knight")
 public class BraveKnight {
     public void saying(String str,User user) throws Exception{ 
         System.out.println("我是骑士..(切点方法)");
         //throw new Exception();
     }
 }

切面类

 package aop;
 
 import java.util.Arrays;
 /**
  * 注解方式声明aop
  * 1.用@Aspect注解将类声明为切面(如果用@Component("")注解注释为一个bean对象,那么就要在spring配置文件中开启注解扫描,<context:component-scan base-package="com.cjh.aop2"/>
  *      否则要在spring配置文件中声明一个bean对象)
  * 2.在切面需要实现相应方法的前面加上相应的注释,也就是通知类型。
  * 3.此处有环绕通知,环绕通知方法一定要有ProceedingJoinPoint类型的参数传入,然后执行对应的proceed()方法,环绕才能实现。
  */
 @Component("annotationTest")
 @Aspect
 public class AnnotationTest {
     //定义切点
     @Pointcut("execution(* *.saying(..))")
     public void sayings(){}
     /**
      * 前置通知(注解中的sayings()方法,其实就是上面定义pointcut切点注解所修饰的方法名,那只是个代理对象,不需要写具体方法,
      * 相当于xml声明切面的id名,如下,相当于id="embark",用于供其他通知类型引用)
      * <aop:config>
         <aop:aspect ref="mistrel">
             <!-- 定义切点 -->
             <aop:pointcut expression="execution(* *.saying(..))" id="embark"/>
             <!-- 声明前置通知 (在切点方法被执行前调用) -->
             <aop:before method="beforSay" pointcut-ref="embark"/>
             <!-- 声明后置通知 (在切点方法被执行后调用) -->
             <aop:after method="afterSay" pointcut-ref="embark"/>
         </aop:aspect>
        </aop:config>
      */
     @Before("sayings()")
     public void sayHello(){
         System.out.println("注解类型前置通知");
     }
     //后置通知
     @After("sayings()")
     public void sayGoodbey(){
         System.out.println("注解类型后置通知");
     }
     //环绕通知。注意要有ProceedingJoinPoint参数传入。
     @Around("sayings()")
     public void sayAround(ProceedingJoinPoint joinPoint) throws Throwable{
         System.out.println("注解类型环绕通知..环绕前");
         Object[] args = joinPoint.getArgs();
         Signature signature = joinPoint.getSignature();
         MethodSignature methodSignature = (MethodSignature) signature;
         //2.最关键的一步:通过这获取到方法的所有参数名称的字符串数组
         String[] parameterNames = methodSignature.getParameterNames();
         System.out.println("parameterNames"+Arrays.toString(parameterNames));
         joinPoint.proceed();//执行方法
         System.out.println("注解类型环绕通知..环绕后");
     }
 }

测试类

package aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 
 * @author Caijh
 * email:codecjh@163.com
 * 2017年7月11日 下午6:27:06
 */
public class Test {
    public static void main(String[] args) throws Exception {
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
        BraveKnight br = (BraveKnight) ac.getBean("knight");
        User user = new User();
        user.setAge(24);
        br.saying("zhangfei",user);
    }
}

配置文件

<?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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="aop"/>
    <!-- 开启aop注解方式,此步骤s不能少,这样java类中的aop注解才会生效 -->
    <aop:aspectj-autoproxy/>
</beans>

@Pointcut注解详解:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
括号中各个pattern分别表示:

修饰符匹配(modifier-pattern?)
返回值匹配(ret-type-pattern)可以为表示任何返回值,全路径的类名等
类路径匹配(declaring-type-pattern?)
方法名匹配(name-pattern)可以指定方法名 或者 代表所有, set 代表以set开头的所有方法
参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用“
”来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(…)表示零个或多个任意参数
异常类型匹配(throws-pattern?)
其中后面跟着“?”的是可选项

1)execution(* *(..))  
//表示匹配所有方法  
2)execution(public * com. savage.service.UserService.*(..))  
//表示匹配com.savage.server.UserService中所有的公有方法  
3)execution(* com.savage.server..*.*(..))  
//表示匹配com.savage.server包及其子包下的所有方法 

拓展一些没用的
Spring AOP采用的是动态代理,在运行期间对业务方法进行增强,所以不会生成新类,对于动态代理技术,Spring AOP提供了对JDK动态代理的支持以及CGLib的支持。
JDK动态代理只能为接口创建动态代理实例,而不能对类创建动态代理。需要获得被目标类的接口信息(应用Java的反射技术),生成一个实现了代理接口的动态代理类(字节码),再通过反射机制获得动态代理类的构造函数,利用构造函数生成动态代理类的实例对象,在调用具体方法前调用invokeHandler方法来处理。
采用Cglib动态代理可以对没有实现接口的类产生代理,实际上是生成了目标类的子类来增强

重载与重写
重载:方法名相同, 参数列表不同的方法之间构成重载; 参数列表不同又包括参数数量, 参数类型, 参数顺序的不同.重载的判断只有这两条, 与方法的修饰符, 返回值类型都无关,修饰符返回值类型不同也叫重载
重写: 1. 三同一大: 返回值类型, 方法名, 参数列表必须与父类相同(返回值类型在java1.5中允许协变返回类型, 就是重写之后的方法的返回值可以是重写之前方法的子类); 一大是指访问权限大于等于父类的访问权限
    2. 子类方法只能抛出比父类方法更小的异常或者不抛出异常
    3. 被重写的方法不能有final,private, static修饰符. 因为final不允许被子类继承; 而private方法隐含是final类型, 且只能在类中被访问, 子类是无权访问的. 子类中只能定义一个与父类完全相同的方法, 而不能称之为重写;

spring事务实现原理:动态代理
对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:

1获取连接 Connection con = DriverManager.getConnection()
2开启事务con.setAutoCommit(true/false);
3执行CRUD
4提交事务/回滚事务 con.commit() / con.rollback();
5关闭连接 conn.close();

使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成。 那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。下面简单地介绍下,注解方式为例子
配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值