aop可以用来在不修改原代码的情况下为原代码 添加增强功能,先写一个使用的小例子:
我们先定义一个功能代码:
@Component
public class Client {
public void print(){
System.out.println("client print");
}
}
现在需要切入aop增强其功能,所要做的只有一件事:定义增强切面(其中包括切点以及通知):
@Aspect
@Component
public class Jaop {
@Pointcut("execution(* Client.*(..))") //定义切点,execution指定需要切入的地方,这里指Client类的所有方法
public void print(){} //或者这样指定太麻烦,也可以自定义一个注解,然后将execution的值指定为该注解,这样使用了该注解的方法都会被增强功能
@Before("print()")
public void beforePrint() {
System.out.println("before print");
}
@After("print()")
public void afterPrint() {
System.out.println("after print");
}
@Around("print()")
public void around(ProceedingJoinPoint p) throws Throwable {
System.out.println("around before");
p.proceed();
System.out.println("around after");
}
}
其实这样就可以了,如果调用Client的print方法时会触发aop的增强功能。
那aop的原理是什么呢?其实就是动态代理,当然动态代理包括JDK动态代理和cglib动态代理,下面介绍下源码解析:
aop的最开始在于AnnotationAwareAspectJAutoProxyCreator类(自动代理创建器),查看它的类结构图可以发现它实现了BeanPostProcessor接口,那么一切就清楚了,应该是所有的Bean实例化前后会执行这个Bean后处理器来创建代理(给实例对象创建代理对象来增强功能的原理就不说了)。下面来看看是不是这样。
图片.png开启AOP后,Spring会对AnnotationAwareAspectJAutoProxyCreator进行自动注册:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
那么这个AnnotationAwareAspectJAutoProxyCreator做了哪些事呢?
我们先看看它的顶层接口BeanPostProcessor的定义:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor接口提供了两个方法,从命名可以看出来一个是在Bean实例化之前执行,一个是在Bean实例化之后执行。
而前面类结构图中的AbstractAutoProxyCreator中就重写了postProcessBeforeInitialization方法(重点):
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); *******************
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); //这里就创建了目标Bean的代理对象!!!!!!!!
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
postProcessBeforeInitialization方法中的判断条件什么的就不说了,主要是getAdvicesAndAdvisorsForBean与createProxy那两句,这两句就获取了所有可以应用到该Bean上的增强方法并创建了代理对象。先看getAdvicesAndAdvisorsForBean方法:
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors(); ********
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); ********
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors; //返回了所有可以应用到该Bean上的增强方法
}
上面的findCandidateAdvisors就是获取了所有的增强方法,它的具体做法大概分几步:1、获取所有Aspect注解的增强类的beanName(直接获取beanDefinitionNames集合进行条件过滤就行)。2、再通过beanName获得所有对应的Advisor增强对象。
获取了所有的增强对象后,就需要再过滤一遍看看哪些可以应用在当前的Bean上,那就是findAdvisorsThatCanApply做的事了,这个方法里面最主要的就是canApply方法:
//可以看出就是看Advisor的增强条件是不是和该Bean的方法匹配
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
至此,前面的代码先是在Bean实例化前进入了Bean后处理器,然后获取了所有符合条件可以应用在该Bean的Advisor。那后面顺理成章创建动态代理将增强功能织入就OK了,继续。
下面就看看怎么创建Proxy的
从postProcessBeforeInitialization的createProxy进去是这个样子:
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
... ...
ProxyFactory proxyFactory = new ProxyFactory();
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true); **********
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor); **********
}
proxyFactory.setTargetSource(targetSource); **********
return proxyFactory.getProxy(getProxyClassLoader()); **********
}
最后可以看出,生成代理对象由proxyFactory完成,只需要将类加载器、接口等参数传给它就行了。
不对,好像少了什么....JDK的动态代理需要Handler啊,这里需要把Advisor对象转换成Handler吧,找找在哪.....
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
上面最后一句显示Handler的参数是this,说明是createAopProxy()返回的啊,进去看看,果然:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
... ...
return new JdkDynamicAopProxy(config);
}
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
... ...
}
好了,AOP的源码分析基本结束了,总结一下过程:
1、注册一个Bean后处理器并重写了postProcessBeforeInitialization方法来对Bean实例化前做操作,在处理器中进行后几步的操作:
2、获取beanFactory中注册的所有Advisor(即@Aspect注解的)的beanName,并获取对象。
3、过滤出可以应用在当前bean上的所有Advisor。
4、创建ProxyFactory,并将classLoader、interface等参数传递给它
5、以Advisor为参数创建InvocationHandler
6、Proxy.newProxyInstance。三个参数都有了(classLoader、interface、Handler)
网友评论