Spring源码-AOP
1.AOP基础概念
1.1两种代理模式
CGLIB和JDK动态代理。(这里不详细讲)
1.2.SpringAOP的基础概念
ProxyFactory :Spring中进行了封装,封装出来的类叫做ProxyFactory,封装了CGLIB和JDK动态代理
Spring利用ProxyFactory来生成代理对象
示例代码:
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("before...");Object result = invocation.proceed();System.out.println("after...");return result;}
});
UserInterface userService = (UserInterface) proxyFactory.getProxy();
userService.test();
SpringAOP涉及到的设计模式:责任链模式
代理对象在执行某个方法的时候,如果存在执行链,那么会一个一个的执行
注意:AspectJ是在编译时对字节码进行了修改(增强),而SpringAOP是在运行的时候,调用相关的代理逻辑、
1.3 Advice的分类
共5种,如下:
- Before Advice:方法之前执行
- After returning advice:方法return后执行
- After throwing advice:方法抛异常后执行
- After (finally) advice:方法执行完finally之后执行,这是最后的,比return更后
- Around advice:这是功能最强大的Advice,可以自定义执行顺序
注意:ThrowsAdvice 中没有固定的方法供我们重写,开放了异常的类型给我们去写。
1.4 Pointcut
切点:方法匹配Advice的时候会用到它,它是一个验证逻辑(验证哪些方法需要被AOP)
如果Pointcut匹配了,之后才会执行advice
包含ClassFilter和MethodMatcher
示例代码:
UserService target = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(new PointcutAdvisor() {@Overridepublic Pointcut getPointcut() {return new StaticMethodMatcherPointcut() {@Overridepublic boolean matches(Method method, Class<?> targetClass) {return method.getName().equals("testAbc");// 切点匹配}};}@Overridepublic Advice getAdvice() {return new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("before...");Object result = invocation.proceed();System.out.println("after...");return result;}};}@Overridepublic boolean isPerInstance() {return false;}
});
UserInterface userService = (UserInterface) proxyFactory.getProxy();
userService.test();
ProxyFactoryBean
通过这种方法来定义一个UserService的Bean,并且是经过了AOP的。但是这种方式只能针对某一个
Bean。它是一个FactoryBean,所以利用的就是FactoryBean技术,间接的将UserService的代理对象作为了Bean。
@Bean
public ProxyFactoryBean userServiceProxy(){UserService userService = new UserService();ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();proxyFactoryBean.setTarget(userService);proxyFactoryBean.addAdvice(new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("before...");Object result = invocation.proceed();System.out.println("after...");return result;}});return proxyFactoryBean;
}
1.5使用@Aspect注解
加了Aspect注解,并且这个类是bean,那么他就是一个切面bean,之后在初始化后就会解析这个bean中的Pointcut和Advice
AnnotationAwareAspectJAutoProxyCreator: 使用这个类配合@Aspect就可以实现AOP
1.6 Advisor(核心)
Advisor = Advice(代理逻辑) + Pointcut(切点规则)
1.7 概念总结
Aspect:表示切面,比如被@Aspect注解的类就是切面,可以在切面中去定义Pointcut、Advice等等
Join point:就是被代理的方法
Advice:代理逻辑
Pointcut:表示切点(规则),用来匹配一个或多个连接点
Target object:目标对象,被代理对象
AOP proxy:表示代理工厂
Introduction:可以为某个类介绍接口
Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译时期(比如 Aspejctj),或者运行时,比如Spring AOP
补充:weawing
在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入、类加载期织入和运行期织入。编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。
AspectJ采用编译期织入和类加载期织入的方式织入切面,是语言级的AOP实现,提供了完备的AOP支持。它用AspectJ语言定义切面,在编译期或类加载期将切面织入到Java类中。
AspectJ提供了两种切面织入方式,第一种通过特殊编译器,在编译期,将AspectJ语言编写的切面类织入到Java类中,可以通过一个Ant或Maven任务来完成这个操作;第二种方式是类加载期织入,也简称为LTW(Load Time Weaving)。