1、AOP 底层原理及使用动态代理
两种动态代理
第一种有接口情况,使用JDK动态代理
创建接口实现类的代理对象,增强类的方法
第二种没有接口情况,使用CGLIB动态代理
创建当前类子类的代理对象,增强类的方法
2、调用 newProxyInstance 方法
static Object newProxyInstance(ClassLoader loader, 类<?> interfaces, InvocationHandler h)
返回指定接口代理类的实例,该接口将方法调用分派给指定的调用处理程序
方法有三个参数:
第一参数:类加载器
第二参数: 增强方法所在的类, 这个类实现的接口,支持多个接口
第三参数:实现这个接口 InvocationHandler,创建代理对象,写增强的方法
3、编写JDK动态代理代码
可看proxy包
3.1、创建接口,定义方法
3.2、创建接口实现类,实现方法
4、AOP术语
4.1、连接点
类里面可以被增强的方法叫做连接点
4.2、切入点
实际真正被增强的方法,称为切入点
4.3、通知(增强)
1、实际增强的逻辑部分称为通知
2、通知的类型
2.1、前置通知 @Before
2.2、后置通知 @After
2.3、环绕通知 @Around
@Around(value = “execution ( * com.example.demo.aop.aspect.User.run (…))”)
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕之前 ........... ");
joinPoint.proceed();
System.out.println("环绕之后 ........... ");
}
2.4、异常通知 @AfterThrowing
2.5、最终通知 @AfterReturning finally
无异常时执行顺序: 环绕之前 -> Before -> run -> AfterReturning -> After -> 环绕之后
有异常时执行顺序: 环绕之前 -> Before -> AfterThrowing -> After
4.4、切面
动作,把通知应用到切面点的过程
5、AOP操作
5.1、Spring框架中一般都是基于AspectJ实现AOP操作
1.1 什么是AspectJ
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
1.2 基于AspectJ实现AOP操作
1、 基于xml配置文件实现
2、 基于注解方式实现(使用)
1.3 在项目工程中引入AOP相关依赖
1.4 切入表达式
1、切入点表达式的作用: 知道对哪个类里面的哪个方法进行增强
5.2、语法结构:
execution: ( [方法返回类型] [返回路径] [类全路径] [方法名称] ([参数列表]) )
举例一:对 com.example.demo.aop.proxy.UserDao 里面的add 方法进行增强
execution: (* com.example.demo.aop.proxy.UserDao.add(…))
举例二:对 com.example.demo.aop.proxy.UserDao 里面的所有方法进行增强
execution: (* com.example.demo.aop.proxy.UserDao.(…))
举例三:对 com.example.demo.aop.proxy 包里面的所有类,以及类里面的所有方法进行增强
execution: ( com.example.demo.aop.proxy..(…))
6、AOP进行通知的配置
可以看aop/bean1.xml;/aop/aspect
6.1、在spring配置文件中,开启注解扫描
<context:component-scan base-package="com.example.demo.aop.aspect"></context:component-scan>
6.2、使用注解创建User和UserProxy对象
6.3、在增强类上添加注解@Aspect
@Component
@Aspect
public class UserProxy
6.4、在spring配置文件中,开启生成代理对象
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
7、AOP相同切入点抽取
使用 @Pointcut 进行抽取
@Pointcut(value = "execution(* com.example.demo.aop.aspect.User.run(..))")
public void pointCutDemo(){
}
@Before(value = "pointCutDemo()")
public void before(){
System.out.println("Before ........... ");
}
8、多个增强类对同一个方法进行增强,设置优先级
8.1 在增强类上面添加注解 @Order(数字类型值),数字值越小,优先级越高
@Order(1); 可看PersonProxy
不加order无异常时执行顺序: 环绕之前 -> Before -> run -> AfterReturning -> After -> 环绕之后
加order无异常时执行顺序:Person before -> 环绕之前 -> Before -> run -> AfterReturning -> After -> 环绕之后
9、Aspectj 配置文件
可以看aop/bean2.xml;/aop/aspectXml
9.1、创建类,在类里面定义方法
9.2、创建增强类,编写增强逻辑
在增强类里面,创建方法,让不同方法代表不同通知类型
9.3、在 Spring 配置文件中配置切入点
<bean id="book" class="com.example.demo.aop.aspectXml.Book"></bean>
<bean id="bookProxy" class="com.example.demo.aop.aspectXml.BookProxy"></bean>
<aop:config>
<aop:pointcut id="pointC" expression="execution(* com.example.demo.aop.aspectXml.Book.buy(..))"/>
<aop:aspect ref="bookProxy">
<aop:before method="before" pointcut-ref="pointC"></aop:before>
</aop:aspect>
</aop:config>
10、完全注解开发
10.1 创建配置类,不需要配置xml文件开发
@ComponentScan(basePackages = “com.example.demo.aop”)
@EnableAspectJAutoProxy(proxyTargetClass = true) 替代
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 生成代理对象
@ComponentScan(basePackages = "com.example.demo.aop")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AllAnnoAspect {
}