AOP概念:
切入点(pointcut):需要增强的目标方法。
连接点(joinpoint):方法连接点,方法有关的前前后后都是连接点。即切点的全集。
通知(advice):某个方法在执行前或执行后要完成的工作
切面(aspect):切点和通知共同定义了切面的全部功能——它是什么,在何时何处完成其功能,切面就是横切关注点的抽象。
动态代理:Spring AOP使用动态代理,所谓动态代理即AOP框架不会修改原来的对象,而是在需要的时候重新生成一个代理对象,这个代理对象包含了目标对象的全部发放,并且在指定的切点做了处理,而且最终还是回调原对象的方法。
动态代理有两种方式,JDK动态代理和CGLIB动态代理。
JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口,其核心是InvocationHandler接口和Proxy类。
如果目标类没有实现接口,那就要选择使用CGLIB来动态代理目标类。CGLIB是通过继承的方式做的动态代理,因此,如果某个类被标记为final,那么它是无法使用CGLIB做动态代理。CGLIB会使生成的代理类继承当前的对象,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。
1、AOP基本搭建:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.8.RELEASE</version> </dependency>
@Configuration @ComponentScan(value = "com.aop.test") @EnableAspectJAutoProxy public class ConfigAOP { }
@Aspect @Component public class LogAspects { @Pointcut("execution( public int com.aop.test.MathCaculator.div(..))") public void pointcut(){ } @Before("pointcut()") public void logstart(JoinPoint joinPoint){ System.out.println("@Before aop方法运行开始。。。。获取方法名:"+joinPoint.getSignature().getName()+ "获取方法的参数列表:" +Arrays.asList(joinPoint.getArgs())); } @After("pointcut()") public void logEnd(){ System.out.println("@After: aop方法运算结束"); } @AfterReturning("pointcut()") public void logReturn(){ System.out.println("@AfterReturning: aop方法返回"); } @AfterThrowing(value = "pointcut()",throwing = "exception") public void logException(Exception exception){ System.out.println("@AfterThrowing 打印aop方法异常信息:"); } }
@Component public class MathCaculator { public int div(int a,int b) throws Exception { System.out.println("除法的方法主体"); return a/b; } }
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(ConfigAOP.class); System.out.println("容器初始化成功"); MathCaculator MathCaculator = annotationConfigApplicationContext.getBean(MathCaculator.class); MathCaculator.div(1,0); annotationConfigApplicationContext.close(); } }
2、AOP的简单注解:
在配置类中:@EnableAspectJAutoProxy(开启基于注解的aop模式)
切面类:@Aspect(告诉Spring哪个是切面类,切面类也要要注解@Component才能将切面类加入到注解中)
3、AOP源码解析(aop原理即:给容器中注册了哪些组件,这些组件什么时候工作,以及组件功能是什么):
@EnableAspectJAutoProxy 开始源码分析:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { }
- 在这里可以看到导入了一个组件AspectJAutoProxyRegistrar.class,利用它,可以自定义注册bean。
org.springframework.aop.config.internalAutoProxyCreator -> org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
给容器中注册一个类型为AnnotationAwareAspectJAutoProxyCreator名字为internalAutoProxyCreator的bean 。
- 给容器注入AnnotationAwareAspectJAutoProxyCreator的作用:
该类实现了接口SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware,其中BeanPostProcessor接口关注在bean初始化前后做的事情,BeanFactoryAware接口关注自动装配BeanFactory
流程:
1)传入配置类,创建ioc容器。
AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(ConfigAOP.class);
2)注册配置类,调用refresh()刷新容器
3)registerBeanPostProcessors(beanFactory); 注册bean的后置处理器来方便拦截bean的创建