学习内容
1、AOP简述
2、Spring AOP简介
3、Spring AOP设计
4、Spring AOP实现
一、AOP简述:
AOP:Aspct-Oriented Programming,意思为面向切面。AOP把软件系统分为两个部分:核心关注点和横切关注点。核销关注点即为业务代码,而横切关注点为业务无关代码,例如权限认证、日志、事务处理等。AOP技术有AspectJ、JBoss-AOP、Spring AOP等。
1、Aspect(切面):将影响了多个类的公共行为封装到一个可重用模块,该模块即为切面。
2、Joinpoint(连接点): 一个应用执行过程中能够插入一个切面的点。
SpringAOP的连接点只能是方法。
3、Pointcut(切点): 连接点的集合。
4、Advice(通知/增强):在特定的连接点,AOP框架执行的动作。描述切面要完成的工作,还解决何时执行这个工作。Spring 切面可应用的 5 种通知类型:
a、Before——在方法调用之前调用通知
b、After——在方法完成之后调用通知,无论方法执行成功与否
c、After-returning——在方法执行成功之后调用通知
d、After-throwing——在方法抛出异常后进行通知
e、Around——通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行
5、Introduction(引入):引入是一种特殊的增强,它为目标类添加一些属性和方法。
如果一个业务类没有实现某个接口,通过AOP的引介功能,可以动态地为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。
Spring允许引入新的接口到任何被通知的对象。例如,可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口。
6、Target Object(目标对象): 包含连接点的对象。也被称作被通知或被代理对象。
7、Weave(织入): 织入是将切面应用到目标对象来创建的代理对象过程。根据不同的实现技术,AOP有三种织入的方式:
a、编译期织入,这要求使用特殊的Java编译器。
b、类装载期织入,这要求使用特殊的类装载器。
c、动态代理织入,在运行期为目标类添加增强生成子类的方式。
SpringAOP采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
二、Spring AOP简介
1、Spring AOP对相关术语的实现
a、Advice
继承关系,以实现类MethodBeforeAdvice为例
实现MethodBeforeAdvice的before回调方法就行
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method var1, Object[] var2, Object var3) throws Throwable;
}
Spring org.springframework.aop 下的其他Advice实现类,例如AfterReturningAdvice等,设计都是一致的。
b、Pointcut
继承关系,以实现类JdkRegexpMethodPointcut为例
public interface Pointcut {
Pointcut TRUE = TruePointcut.INSTANCE;
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
public interface MethodMatcher {
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
boolean matches(Method var1, Class<?> var2);
boolean isRuntime();
//当返回true时,表名当前方法需要增强。以JDK动态代理织入方式为例,该方法的
//调用在,拦截接口的invoke()方法中调用
boolean matches(Method var1, Class<?> var2, Object[] var3);
}
除了JdkRegexpMethodPointcut,还有NameMatchMethodPointcut,以方法名作为匹配
c、Advisor
用于结合,Advice和Pointcut,以DefaultPointcutAdvisor为例,继承关系为
三、Spring AOP设计
1、设计
Spring AOP的技术实现是以动态代理为基础,也就是说Spring AOP功能就是使用动态代理实现的。
四、Spring AOP实现
1、如何生成代理对象?ProxyCreatorSupport
继承关系
实现子类有三个
AspectJProxyFactory:支持集成AspectJ和Spring。
ProxyFactoryBean:支持在Ioc容器中完成声明配置Spring AOP.
ProxyFactory:支持编程式的使用Sprng AOP功能。
2、ProxyFactoryBean、ProxtyFactory实现AOP功能
使用ProxyFactoryBean,是Ioc环境中创建Aop应用的最底层方式,最为灵活。Spring通过ProxyFactoryBean完成对AOP功能的封装。
如何使用?
//定义一个接口
public interface UserDao {
void addUser();
}
//目标对象实现接口并重写方法
public class UserDaoImpl implements UserDao {
@Override
public void addUser() {
System.out.println("新增用户");
}
}
//实现增强类的接口
public class LogBefore implements MethodBeforeAdvice {
//arg0 目标类的方法
arg1 目标类的入参数
arg2 目标类
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("添加日志");
}
}
ProxtyFactory以编程形式
public class Test {
public static void main(String[] args) throws Exception{
LogBefore log = new LogBefore();
UserDao userDao = new UserDaoImpl();
ProxyFactory proxyf = new ProxyFactory();
//设置目标对象
proxyf.setTarget(userDao);
//设置增强类对象
proxyf.addAdvice(log);
//获得代理对象
UserDao up = proxyf.getProxy();
up.addUser();
}
}
ProxyFactoryBean通过xml配置代理。
<bean id="logBefore" class="com.cong.LogBefore"/>
<bean id="target" class="com.cong.UserDaoImpl"/>
<bean id="userDao" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.cong.UserDao"
p:interceptorNames="logBefore"
p:target-ref="target"/>
target:代理的目标对象
proxyInterfaces:代理所需要实现的接口,可以多个接口。该属性还有一个别名是Interfaces
interceptorNames:需要植入目标对象的bean列表。采用bean的名称指定。
这些bean必须实现类 org.aopalliance.intercept.MethodInterceptor
或 org.springframework.aop.Advisor的bean ,配置中的顺序对应调用的顺序。
proxyTargetClass:是否对类进行代理,而不是进行对接口进行代理。
设置为true时,使用CGLib代理,且proxyInterfaces属性被ProxyFactoryBean忽略。
3、代理对象的生成
ProxyFactoryBean为FactoryBean,所以,以getObject()为入口可知,代理对象的生成,由AopProxy生成,其实现类有两个,Cglib2AopProxy、JdkDynamicProxy,所以Spring分别通过CGLIB和JDK来生成代理对象。
而AopProxy的生成由DefaultAopProxyFactory来生成,具体生成哪个实现类由代理的模板类是否实现接口来判断,如果是则生成JdkDynamicAopProxy,否则使用Cglib2AopProxy,或者配置强制使用Cglib2AopProxy。这两个类都有直接实现各自代理的拦截器接口,如JdkDynamicAopProxy实现了InvocationHandler接口的invoke()方法,Cglib2AopProxy实现了DynamicAdvicedInterceptor接口的intercept()方法,所以Spring AOP具体的增强就是通过拦截器来完成的。