Spring注解驱动开发-AOP(四)
关联文章:
AOP
指在程序运行期间动态的将某段代码切入到指定方法位置进行运行的编程方式
静态代理:需要事先写好代理类,缺点是每个业务类度需要一个代理类,不灵活
动态代理:运行时动态生成代理类。缺点生成代理类和调用方法需要额外花费时间
- JDK动态代理:基于Java反射机制,必须要实现接口的业务类才能用这种方法生成代理类。
- cglib动态代理:基于ASM机制实现,通过生成业务类的子类作为代理类
AOP当中的概念:
1、切入点(Pointcut):在哪些类,哪些方法上切入(where);
2、增强(Advice):早期翻译为通知,在方法执行的什么时机(when:方法前/方法后/方法前后)做什么(what:增强的功能);
3、切面(Aspect):切面=切入点+通知,通俗点就是:什么时机,什么地点,做什么!
4、织入(Weaving):把切面加入到对象,并创建出代理对象的过程。(该过程由Spring来完成)。
步骤:
1.导入aop模块:spring-aspects依赖
2.定义一个业务逻辑类(MathCaculator);在运行时将日志打印
3.定义一个日志切面类(LogAspects);切面类的方法需要动态感知MathCaculator里的方法运行到哪里了,然后执行
通知方法:
前置通知(@Before):在目标方法运行之前运行
后置通知(@After):在目标方法运行结束后运行。无论方法正常还是异常
返回通知(@AfterReturning):在目标方法正常返回之后运行
异常通知(@@AfterThrowing):在目标方法出现异常之后运行
环绕通知(@Around):在目标方法执行前和执行后执行
4.通知注解,告诉切面类在何时何地切入
5.然后把切面类和业务逻辑类加入容器
6.告诉spring哪个是切面类(给切面类贴上@Aspect)
7.给配置类贴上@EnableAspectJAutoProxy【开启基于注解的AOP模式】
例子:
[code]@Component public class MathCaculator { public int calculator(int i, int j) { System.out.println("MathCaculator.calculator()"); return i/j; } }
切面类
[code]@Aspect//切面类 public class LogAspects { @Pointcut("execution(public int com.zxc.aop.MathCaculator.calculator(..))") public void pointCut() {} //前置通知 @Before("pointCut()") public void logStart(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); System.out.println("@Before.."+joinPoint.getSignature().getName()+"方法参数{"+args+"}"); } //后置通知,出现异常也会调用 @After("pointCut()") public void logEnd() { System.out.println("@After.."); } //返回通知 @AfterReturning(value="pointCut()",returning="obj") public void logReturn(Object obj) { System.out.println("@AfterReturning.."+"LogAspects.logReturn()..返回值:"+obj); } //异常通知 //注意JoinPoint一定要出现在 参数表第一位,不然异常 @AfterThrowing(value="pointCut()",throwing="e") public void logException(JoinPoint joinPoint,Exception e) { System.out.println("@AfterThrowing.."+joinPoint.getSignature().getName()+"LogAspects.logException()..异常信息"+e); } }
配置类,将切面类和业务逻辑类都加入到容器中,给配置类加 @EnableAspectJAutoProxy 注解
[code]@Configuration @EnableAspectJAutoProxy//开启基于注解的AOP模式 public class MainConfigOfAop { @Bean public MathCaculator mathCal() { return new MathCaculator(); } @Bean public LogAspects logAspects() { return new LogAspects(); } }
测试
[code] @Test public void test1() throws Exception { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfigOfAop.class); MathCaculator bean = ac.getBean(MathCaculator.class); bean.calculator(2, 0); }
结果
[code]@Before..calculator方法参数{[Ljava.lang.Object;@63070bab} MathCaculator.calculator() @After.. @AfterThrowing..calculatorLogAspects.logException()..异常信息java.lang.ArithmeticException: / by zero
xml开启基于注解的AOP模式
<aop:aspectj-autoproxy/>
(开启基于注解的AOP模式)原理
@EnableAspectJAutoProxy是什么? 看给容器注册了什么组件,这个组组件什么时候工作,这个组件的功能
[code]@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) // ==>看这里 public @interface EnableAspectJAutoProxy { /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. */ boolean proxyTargetClass() default false; /** * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. * Off by default, i.e. no guarantees that {@code AopContext} access will work. * @since 4.3.1 */ boolean exposeProxy() default false; }
1.@Import(AspectJAutoProxyRegistrar.class),给容器导入
AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar
2.利用AspectJAutoProxyRegistrar 自定义给容器注册bean;
internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator
给容器注册一个 AnnotationAwareAspectJAutoProxyCreator
3.AnnotationAwareAspectJAutoProxyCreator
-> AspectJAwareAdvisorAutoProxyCreator
-> AbstractAdvisorAutoProxyCreator
->AbstractAutoProxyCreator
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
关注后置处理器(在bean初始化完成前后做事情),自动装配BeanFactory
AbstractAutoProxyCreator.setBeanFactory();
AbstractAutoProxyCreator.后置处理器逻辑
AbstractAdvisorAutoProxyCreator.setBeanFactory(); -->initBeanFactory()
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()
流程
1.传入主配置类,创建ioc容器
2.注册配置类,调用refresh(),刷新容器
3.// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);; 注册bean的后置处理器来方便拦截bean的创建
1.先获取ioc容器中已经定义了的需要创建对象的所有BeanPostProcessor
2.给容器中加别的BeanPostProcessor
3.优先注册实现PriorityOrdered接口的BeanPostProcessor
4.再给容器中注册实现了Ordered接口的BeanPostProcessor
5.注册没实现优先级接口的BeanPostProcessor
6.注册BeanPostProcessor,实际就是创建BeanPostProcessor对象,保存再容器中
创建 internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator 】
================看不懂,未完待续。。。。
- spring-redis缓存方案学习三:基于aop的自定义注解开发
- Spring AOP编程-aspectJ注解开发
- Spring基于xml配置与注解驱动开发(二)
- Spring 注解驱动开发
- Spring整合JDBC、Spring的AOP事务开发、Spring注解整理
- Spring AOP编程-aspectJ注解开发(@Pointcut声明切点)
- spring框架的学习(五)——Spring使用AspectJ进行AOP的开发:注解方式
- spring中基于注解的aop实用开发
- 【视频分享】尚硅谷Java视频教程_Spring注解驱动开发视频教程
- Spring 【Aspectj】进行AOP开发 (【注解】方式)
- 一步一步实现Spring4 + Hibernate4 + Freemarker2 的注解驱动开发(一. 环境搭建)
- 一步一步实现Spring4 + Hibernate4 + Freemarker2 的注解驱动开发(二.应用配置)
- spring中AOP 注解开发示例详解
- Spring再学习-Aop注解开发(三)
- Spring的AOP的AspectJ的开发:(注解)
- 一步一步实现Spring4 + Hibernate4 + Freemarker2 的注解驱动开发(三.应用代码)
- spring中AOP 注解开发示例详解
- Spring使用AspectJ进行AOP的开发:注解方式
- Spring整合JDBC、Spring的AOP事务开发、Spring注解整理
- Web框架梳理:第四章:Spring学习入门、Spring属性注入、AOP编程、注解开发