【Spring】 AOP Base
一、AOP概述
  AOP(Aspect Oriented Programing),面向切面编程,AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)
  Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
  AspecJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
二、AOP的术语:
- 连接点(Joinpoint):所谓连接点是指那些被拦截到的点。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点.
- 切入点(Pointcut):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
- 通知/增强(Advice):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.- 前置通知(Before advice):在目标方法被调用之前调用通知方法
- 后置通知(After/finally advice):在目标方法完成之后 调用通知方法,此时不会关心方法的输出是什么
- 返回通知(After returning advice):在目标方法成功执行之后调用通知
- 异常通知(After throwing advice):在目标方法抛出异常之后调用通知
- 环绕通知(Around advice):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
 
- 引介/引入(Introduction):引介是一种特殊的通知,在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field
- 目标对象(Target):代理的目标对象
- 织入(Weaving):是指把增强应用到目标对象来创建新的代理对象的过程. Spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
- 代理(Proxy):一个类被AOP织入增强后,就产生一个结果代理类
- 切面(Aspect):是切入点和通知(引介)的结合  

三、AOP底层原理
Spring的AOP实现机制主要有两种:
- JDK动态代理:对实现了接口的类生成代理
- CGLib代理机制:对类生成代理
详见代理模式
四、Spring 中的AOP
1. 概述
2. 分类
- 基于代理的经典Spring AOP(传统AOP)
- 纯POJO切面;
- @AspectJ注解驱动的切面;
- 注入式AspectJ切面(适用于Spring各版本)。
3. Spring的传统AOP
AOP:不是由Spring定义.AOP联盟的组织定义.
Spring中的通知:(增强代码)
- 前置通知:在目标方法执行前实施增强,要实现的接口org.springframework.aop.MethodBeforeAdvice
- 后置通知:在目标方法执行后实施增强,要实现的接口,org.springframework.aop.AfterReturningAdvice
- 环绕通知:在目标方法执行前后实施增强,要实现的接口,org.aopalliance.intercept.MethodInterceptor
- 异常抛出通知:在方法抛出异常后实施增强,要实现的接口,org.springframework.aop.ThrowsAdvice
- 引介通知:在目标类中添加一些新的方法和属性,要实现的接口,org.springframework.aop.IntroductionInterceptor
针对所有方法的增强:(不带有切点的切面)
需要引入的Maven坐标:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.5.RELEASE</version>
            <!-- 这里要注释掉,因为设置了scope为test是,测试类只能卸载 Maven中的测试包下 -->
            <!-- <scope>test</scope> -->
        </dependency>
编写被代理对象
接口:
public interface ICustomerDao {
    public void add();
    public void update();
    public void delete();
    public void find();
}
实现类:
public class CustomerDaoImpl implements ICustomerDao {
    @Override
    public void add() {
        System.out.println("添加客户");
    }
    @Override
    public void update() {
        System.out.println("更新客户");
    }
    @Override
    public void delete() {
        System.out.println("删除客户");
    }
    @Override
    public void find() {
        System.out.println("查询客户");
    }
}
编写增强的代码
前置增强:
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("前置增强。。。。。");
    }
}
生成代理:(在XML中配置生成代理)
<!-- 不带有切点的切面 -->
    <!-- 1.定义目标对象 -->
    <bean id="customerDao"
        class="com.hao.aop.tradition.demo1.CustomerDaoImpl"></bean>
    <!-- 2.定义增强 -->
    <bean id="beforeAdvice"
        class="com.hao.aop.tradition.demo1.MyBeforeAdvice"></bean>
    <!-- 3.Spring支持配置生成代理: -->
    <bean id="customerDaoProxy"
        class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 设置目标对象 -->
        <property name="target" ref="customerDao" />
        <!-- 设置代理要实现的接口 -->
        <property name="proxyInterfaces"
            value="com.hao.aop.tradition.demo1.ICustomerDao"></property>
        <!-- 设置需要织入目标的Advice -->
        <property name="interceptorNames" value="beforeAdvice" />
    </bean>
在XML配置说明:
- 首先要将前面定义的目标对象和增强 注册到Spring 容器中,
- 然后是代理类的配置(主要是这里的配置): 
 通过类- org.springframework.aop.framework.ProxyFactoryBean来设置代理对象,对于这个类,以后有时间要看一下,下面先看一下它在XML中需要配置的属性:- target : 代理的目标对象
- proxyInterfaces : 代理要实现的接口,如果多个接口可以使用以下格式赋值: - <list>
 <value></value>
 ....
 </list>
 
- proxyTargetClass:是否对类代理而不是接口,设置为true时,使用CGLib代理 
- interceptorNames : 需要织入目标的Advice 
- singleton : 返回代理是否为单实例,默认为单例 
- optimize : 当设置为true时,强制使用CGLib 
 
测试
这里要注意的是,要注入代理对象!!!!
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AOPTest1 {
    @Qualifier("customerDaoProxy")
    @Autowired
    private ICustomerDao customerDao;
    @Test
    public void test() {
        customerDao.add();
        customerDao.find();
        customerDao.update();
        customerDao.delete();
    }
}
带有切点的切面:(针对目标对象的某些方法进行增强)
创建目标对象:
这里没有实现接口,这里试下用CGLIB代理的方式
public class OrderDao {
    public void add() {
        System.out.println("添加订单");
    }
    public void delete() {
        System.out.println("删除订单");
    }
    public void find() {
        System.out.println("查询订单");
    }
}
编写增强的类:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyAroundAdvice implements MethodInterceptor{
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("执行方法之前增强.....");
        Object result = invocation.proceed();
        System.out.println("指向方法之后增强.....");
        return result;
    }
}
生成代理(配置生成代理):
<!-- 定义带有切点的切面 -->
    <!-- 定义目标对象 -->
    <bean id="orderDao" class="com.hao.aop.tradition.demo2.OrderDao"></bean>
    <!-- 定义增强 -->
    <bean id="aroundAdvice"
        class="com.hao.aop.tradition.demo2.MyAroundAdvice"></bean>
    <!-- 定义切面 -->
    <bean id="myPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!-- 定义表达式,规定哪些方法执行拦截 -->
        <!-- . 任意字符  * 任意个 -->
        <property name="patterns" value=".*add.*,.*find.*"></property>
        <!-- 应用增强 -->
        <property name="advice" ref="aroundAdvice"/>
    </bean>
    <!-- 定义生成代理对象 -->
    <bean id="orderDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 配置目标 -->
        <property name="target" ref="orderDao"></property>
        <!-- 针对类的代理 -->
        <property name="proxyTargetClass" value="true"></property>
        <!-- 在目标上应用增强 -->
        <property name="interceptorNames" value="myPointcutAdvisor"></property>
    </bean>
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AOPTest2 {
    @Qualifier("orderDaoProxy") //此处注入的是代理对象
    @Autowired
    private OrderDao orderDao;
    @Test
    public void test() {
        orderDao.add();
        orderDao.delete();
        orderDao.find();
    }
}
4. 自动代理
前面的案例中,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护量巨大
  自动创建代理(基于后处理Bean,在Bean创建的过程中完成的增强,生成Bean就是代理。前面利用ProxyFactoryBean代理的方式需要先生成代理对象才可以实现代理功能,而这种方式在Bean的创建过程中就可以完成代码的增强)
  
- BeanNameAutoProxyCreator:根据Bean名称创建代理
- DefaultAdvisorAutoProxyCreator:根据Advisor本身包含信息创建代理
- AnnotationAwareAspectJAutoProxyCreator:基于Bean中的AspectJ 注解进行自动代理
BeanNameAutoProxyCreator
  目标对象和增强,应用前面中的例子,配置示例:
  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
<!-- 自动代理 -->
    <!-- 目标对象 -->
    <bean id="customerDao" class="com.hao.aop.tradition.demo1.CustomerDaoImpl"></bean>
    <bean id="orderDao" class="com.hao.aop.tradition.demo2.OrderDao"></bean>
    <!-- 定义增强-->
    <bean id="beforeAdvice" class="com.hao.aop.tradition.demo1.MyBeforeAdvice"></bean>
    <bean id="aroundAdvice" class="com.hao.aop.tradition.demo2.MyAroundAdvice"></bean>
    <!-- 自动代理:按名称的代理 基于后处理Bean,后处理Bean不需要配置ID-->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames" value="*Dao"/>
        <property name="interceptorNames" value="aroundAdvice"/>
    </bean>
</beans>
测试代码:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.hao.aop.tradition.demo1.ICustomerDao;
import com.hao.aop.tradition.demo2.OrderDao;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class AOPTest3 {
    @Qualifier("customerDao")
    @Autowired
    private ICustomerDao customerDao;
    @Qualifier("orderDao")
    @Autowired
    private OrderDao orderDao;
    @Test
    public void test() {
        orderDao.add();
        orderDao.find();
        customerDao.add();
        customerDao.delete();
    }
}
DefaultAdvisorAutoProxyCreator
根据切面本身包含信息创建代理
配置示例:
<!-- 目标对象 -->
    <bean id="customerDao" class="com.hao.aop.tradition.demo1.CustomerDaoImpl"></bean>
    <bean id="orderDao" class="com.hao.aop.tradition.demo2.OrderDao"></bean>
    <!-- 定义增强-->
    <bean id="beforeAdvice" class="com.hao.aop.tradition.demo1.MyBeforeAdvice"></bean>
    <bean id="aroundAdvice" class="com.hao.aop.tradition.demo2.MyAroundAdvice"></bean>
    <!-- 定义一个带有切点的切面 -->
    <bean id="myPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="pattern" value=".*add.*"/>
        <property name="advice" ref="aroundAdvice"/>
    </bean>
    <!-- 自动生成代理 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
测试代码:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.hao.aop.tradition.demo1.ICustomerDao;
import com.hao.aop.tradition.demo2.OrderDao;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class AOPTest4 {
    @Autowired
    @Qualifier("customerDao")
    private ICustomerDao customerDao;
    @Autowired
    @Qualifier("orderDao")
    private OrderDao orderDao;
    @Test
    public void test() {
        customerDao.add();
        customerDao.update();
        orderDao.add();
        orderDao.delete();
    }
}
区别:基于ProxyFattoryBean的代理与自动代理
- ProxyFactoryBean:先有被代理对象,将被代理对象传入到代理类中生成代理.
- 自动代理基于后处理Bean.在Bean的生成过程中,就产生了代理对象,把代理对象返回.生成Bean已经是代理对象.
5. AspectJ
概述
AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
  AspectJ是一个基于Java语言的AOP框架
  Spring2.0以后新增了对AspectJ切点表达式支持
  @AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
  新版本Spring框架,建议使用AspectJ方式来开发AOP
AspectJ表达式
  在Spring AOP中,要使用AspectJ的切点表达式语言来定义切点。关于Spring AOP的AspectJ切点,最重要的一点就是Spring仅支持AspectJ切点指示器(pointcut designator)的一个子集。Spring是基于代理的,而某些切点表达式是与基于代理的AOP无关的。Spring AOP所支持的AspectJ切点指示器如下:

在Spring中尝试使用AspectJ其他指示器时,将会抛出IllegalArgument-Exception异常。当我们查看如上所展示的这些Spring支持的指示器时,注意只有execution指示器是实际执行匹配的,而其他的指示器都是用来限制匹配的。这说明execution指示器是我们在编写切点定义时最主要使用的指示器。在此基础上,我们使用其他指示器来限制所匹配的切点。
execution 表达式语法:
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

  我们使用execution()指示器选择Performance的perform()方法。方法表达式以“*”号开始,表明了我们不关心方法返回值的类型。然后,我们指定了全限定类名和方法名。对于方法参数列表,我们使用两个点号(..)表明切点要选择任意的perform()方法,无论该方法的入参是什么。

  请注意我们使用了“&&”操作符把execution()和within()指示器连接在一起形成与(and)关系(切点必须匹配所有的指示器)。类似地,我们可以使用“||”操作符来标识或(or)关系,而使用“!”操作符来标识非(not)操作。
  因为“&”在XML中有特殊含义,所以在Spring的XML配置里面描述切点时,我们可以使用and 来代替“&&”。同样,or和not可以分别用来代替“||”和“!”。
AspectJ增强:
- @Before 前置通知,相当于BeforeAdvice
- @AfterReturning 后置通知,相当于AfterReturningAdvice
- @Around 环绕通知,相当于MethodInterceptor
- @AfterThrowing抛出通知,相当于ThrowAdvice
- @After 最终final通知,不管是否异常,该通知都会执行
- @DeclareParents 引介通知,相当于IntroductionInterceptor (了解)
开发步骤
开发之前需要引入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>
基于XML
第一步:编写被增强的类:
 public class ProductDao {
    public int add(){
        System.out.println("添加商品...");
        int d = 10/0;
        return 100;
    }
    public void update(){
        System.out.println("修改商品...");
    }
    public void delete(){
        System.out.println("删除商品...");
    }
    public void find(){
        System.out.println("查询商品...");
    }
}
第二步:定义切面
import org.aspectj.lang.ProceedingJoinPoint;
/**
 * 切面类
 * @author hao
 *
 */
public class MyAspectXML {
    public void before(){
        System.out.println("前置通知...");
    }
    public void afterReturing(Object returnVal){
        System.out.println("后置通知...返回值:"+returnVal);
    }
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("环绕前增强....");
        Object result = proceedingJoinPoint.proceed();
        System.out.println("环绕后增强....");
        return result;
    }
    public void afterThrowing(Throwable e){
        System.out.println("异常通知..."+e.getMessage());
    }
    public void after(){
        System.out.println("最终通知....");
    }
}
第三步:配置applicationContext.xml
<!-- 定义目标对象 -->
    <bean id="productDao" class="com.hao.aop.aspectj.xml.ProductDao"></bean>
    <!-- 定义增强 -->
    <bean id="myAspectXML" class="com.hao.aop.aspectj.xml.MyAspectXML"></bean>
    <aop:config>
        <!-- 定义切点: -->
        <aop:pointcut id="mypointcut" expression="execution(* com.hao.aop.aspectj.xml.ProductDao.add(..))" />
        <aop:aspect ref="myAspectXML">
            <!-- 前置通知 -->
            <aop:before method="before" pointcut-ref="mypointcut"/>
            <!-- 后置通知 -->
            <aop:after-returning method="afterReturing" pointcut-ref="mypointcut" returning="returnVal"/>
            <!-- 环绕通知 -->
            <aop:around method="around" pointcut-ref="mypointcut"/>
            <!-- 异常通知 -->
            <aop:after-throwing method="afterThrowing" pointcut-ref="mypointcut" throwing="e"/>
            <!-- 最终通知 -->
            <aop:after method="after" pointcut-ref="mypointcut"/>
        </aop:aspect>
    </aop:config>
基于注解
第一步:导入aop模块;Spring AOP:(spring-aspects)
第二部:定义一个业务逻辑类:在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
public class UserDao {
    public void add(){
        System.out.println("添加用户");
    }
    public int update(){
        System.out.println("修改用户");
        return 1;
    }
    public void delete(){
        System.out.println("删除用户");
    }
    public void find(){
        System.out.println("查询用户");
        //int d = 1/ 0;
    }
}
第三步:定义一个切面类:切面类里面的方法需要动态感知业务类的方法运行到哪里然后执行;
- 给切面类的目标方法标注何时何地运行(通知注解);
- 必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
/**
 * 切面类:就是切点与增强结合
 *
 * @author hao
 *
 */
@Aspect
public class MyAspect {
    // 定义一个切点
    @Pointcut("execution(* com.hao.aop.aspectj.anno.UserDao.find(..))")
    private void myPointcut() {} // 此方法没有实际的意义,就是为了提供给注解一个修饰的地方
    @Before("execution(* com.hao.aop.aspectj.anno.UserDao.add(..))")
    public void before(JoinPoint joinPoint) {
        System.out.println("前置增强...." + joinPoint);
    }
    @AfterReturning(value = "execution(* com.hao.aop.aspectj.anno.UserDao.update(..))", returning = "returnVal")
    public void afterReturin(Object returnVal) {
        System.out.println("返回增强....方法的返回值:" + returnVal);
    }
    @Around(value = "MyAspect.myPointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕前增强....");
        Object obj = proceedingJoinPoint.proceed();
        System.out.println("环绕后增强....");
        return obj;
    }
    @AfterThrowing(value = "MyAspect.myPointcut()", throwing = "e")
    public void afterThrowing(Throwable e) {
        System.out.println("不好了 出异常了!!!" + e.getMessage());
    }
    @After("MyAspect.myPointcut()")
    public void after() {
        System.out.println("最终/后置通知...");
    }
}
AspectJ的通知类型:
- 前置通知(@Before):logStart:在目标方法(div)运行之前运行
- 后置通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
- 返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
- 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
- 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
- 引介通知(@DeclareParents) ,相当于IntroductionInterceptor (不要求掌握)
切点的定义:
// 定义一个切点
@Pointcut("execution(* com.hao.aop.aspectj.anno.UserDao.find(..))")
private void myPointcut() {} // 此方法没有实际的意义,就是为了提供给注解一个修饰的地方
Advisor和Aspect的区别?
- Advisor:Spring传统意义上的切面:支持一个切点和一个通知的组合.
- Aspect:可以支持多个切点和多个通知的组合.
第四步:开启注解,并将切面类和业务逻辑类(目标方法所在类)都加入到容器中
XML方式:
<!-- 自动生成代理  底层就是AnnotationAwareAspectJAutoProxyCreator -->
    <aop:aspectj-autoproxy />
    <bean id="userDao" class="com.hao.aop.aspectj.anno.UserDao"></bean>
    <bean id="myAspect" class="com.hao.aop.aspectj.anno.MyAspect"></bean>
注解方式
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
    //业务逻辑类加入容器中
    @Bean
    public UserDao userDao(){
        return new UserDao();
    }
    //切面类加入到容器中
    @Bean
    public MyAspect myAspect(){
        return new MyAspect();
    }
}
测试
- 注意加载的配置文件
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=MainConfigOfAOP.class)
//此处的配置文件可以加载java类 或者 XML文件
//@ContextConfiguration("classpath:contextApplication5.xml")
public class AOPTest2 {
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;
    @Test
    public void demo1(){
        userDao.add();
        userDao.delete();
        userDao.update();
        userDao.find();
    }
}
给配置类中加@EnableAspectJAutoProxy【开启基于注解的aop模式】,在Spring中很多的 @EnableXXX(要抽时间整理一下其原理);
总结
- 将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个是切面类(@Aspect)
- 在切面类上的每一个通知方法上标注通知注解,告诉Spring何时何地运行(切入点表达式)
- 开启基于注解的aop模式;@EnableAspectJAutoProxy
6. AOP的实现机制原理(AnnotationAwareAspectJAutoProxyCreator)
AnnotationAwareAspectJAutoProxyCreator 底层的原理
已经整理完,查阅【Spring】AOP注解方式实现机制
【Spring】 AOP Base的更多相关文章
- 【Spring】AOP注解方式实现机制
		一.概述 二.@EnableAspectJAutoProxy 注解分析 三.分析AnnotationAwareAspectJAutoProxyCreator 四.执行流程 1. registerBea ... 
- 【Spring】AOP实现原理(三):创建代理
		AbstractAutoProxyCreator 在AbstractAutoProxyCreator的wrapIfNecessary方法中,调用getAdvicesAndAdvisorsForBean ... 
- 【Spring】AOP实现原理(一):AOP基础知识
		AOP相关概念 在学习AOP实现原理之前,先了解下AOP相关基础知识. AOP面向切面编程,它可以通过预编译方式或者基于动态代理对我们编写的代码进行拦截(也叫增强处理),在方法执行前后可以做一些操作, ... 
- 【Spring】 IOC Base
		一.关于容器 1. ApplicationContext和BeanFactory 2. 配置文件 XML方式 Java-configuration 方式 @Configuration 3. 初始化容器 ... 
- 【Spring】AOP的代理默认是Jdk还是Cglib?
		菜瓜:你觉得AOP是啥 水稻:我觉得吧,AOP是对OOP的补充.通常情况下,OOP代码专注功能的实现,所谓面向切面编程,大多数时候是对某一类对象的方法或者功能进行增强或者抽象 菜瓜:我看你这个理解就挺 ... 
- 【Spring】AOP实现原理(二):Advisor获取
		@EnableAspectJAutoProxy @EnableAspectJAutoProxy注解可以用来开启AOP,那么就从@EnableAspectJAutoProxy入手学习一下Spring A ... 
- 【spring】aop切面通知,日志处理
		1.spring的切面编程 概念原理可以看这里:http://blog.csdn.net/moreevan/article/details/11977115 2.所需要的jar包 maven引入jar ... 
- 【Spring】AOP
		AOP 编程允许你把遍布应用各处的功能分离出来形成可重用的组件,将安全.事务和日志关注点与你的核心业务逻辑相分离. 面向切面编程往往被定义为促使应用程序分离关注点的一项技术.系统由许多不同组件组成,每 ... 
- 【AOP】操作相关术语---【Spring】的【AOP】操作(基于aspectj的xml方式)
		[AOP]操作相关术语 Joinpoint(连接点):类里面哪些方法可以被增强,这些方法称为连接点. Pointcut(切入点):在类里面可以有很多的方法被增强,比如实际操作中,只是增强了类里面add ... 
随机推荐
- Usaco Training [1.3] wormhole
			传送门 解题要素:代码能力 解题步骤:理解题意 - >搜索枚举所有可能的配对情况 - >判断冲突并求解 - >调试 一. 理解题意 这里讲几个不容易理解的点: 1. +x方向 即向右 ... 
- F#周报2019年第32期
			新闻 推出FSharp.Core 4.7,附带netstandard2支持 ML.NET 1.3.1发布 FSharp.SystemTextJson宣告:对于.NET Core的System.Text ... 
- iview自定义实现多级表头
			最近更新: 2018-07-19 注意:最新版iview已经提供多级表头功能 参考 原理:利用多个Table组件通过显示和隐藏thead和tbody来拼接表格(较粗暴) html <div st ... 
- LK的NOIP膜拟赛
			T1 Learn to 签到 [题目描述] 希希最喜欢二进制了.希希最喜欢的运算是\(\wedge\). 希希还喜欢很多\(01\)序列.这些序列一共有\(n\)个,每个的长度为\(m\). 希希有一 ... 
- 60701BMP彩色图像转化为灰度及二值图像
			1 概述 多媒体技术是一门综合了多种学科的新技术,其涉及到计算机科学与技术.通信和网络技术.人工智能技术.微电子技术.数字信号处理.图形处 理技术.声像技术等诸多学科.许多新技术的不断出现和体验,带给 ... 
- Java一个简单的文件工具集
			class FileUtils { //文件目录下文件总数目 public static int fileNumber(File dir) { int filenumber = 0; if(dir.e ... 
- 机器学习tips
			1 为什么随机梯度下降法能work? https://www.zhihu.com/question/27012077中回答者李文哲的解释 2 随机梯度下降法的好处? (1)加快训练速度(2)噪音可 ... 
- 综述 | SLAM回环检测方法
			本文作者任旭倩,公众号:计算机视觉life成员,由于格式原因,公式显示可能出问题,建议阅读原文链接:综述 | SLAM回环检测方法 在视觉SLAM问题中,位姿的估计往往是一个递推的过程,即由上一帧位姿 ... 
- 随笔编号-08  MYSQL 存储过程,5分钟执行调用过程;
			delimiter //DROP PROCEDUREIF EXISTS jdt.day_instan_data_task// CREATE PROCEDURE jdt.day_instan_data_ ... 
- js获取(包括中文)字符串长度与截取字符串
			/** * @param begin 截取开始的索引 * @param num 截取的长度 */ //截取字符串(包括中文) function SetString(str, len) { var st ... 
