您的位置:首页 > 编程语言 > Java开发

Spring注解驱动开发-AOP(四)

2019-03-06 20:44 791 查看

关联文章:

Spring注解驱动开发-组件注册(一)

Spring注解驱动开发-生命周期(二)

Spring注解驱动开发-属性赋值&自动装配(三)

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 】

     ================看不懂,未完待续。。。。

       

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: