Spring AOP
Spring AOP比较常用的使用方式是通过AspectJ表达式声明切入点及处理Advice。
本文介绍继承AbstractAutoProxyCreator的方式来创建代理,区别是这种方式可以对Bean容器初始化的Bean做动态处理,决定是否创建代理、如何创建代理。
AspectJ方式也是创建动态代理,但是相对而言又是一种静态的方式,因为AOP的配置一开始在编译期就已确定了。
结合示例说明
类全名: org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
Spring版本: 4.3.8.RELEASE
创建一个继承AbstractAutoProxyCreator的类
需要实现getAdvicesAndAdvisorsForBean方法以创建代理
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
import org.springframework.beans.BeansException;
public class MyProxyCreator extends AbstractAutoProxyCreator {
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException {
// TODO
}
}
getAdvicesAndAdvisorsForBean方法说明
/**
* Return whether the given bean is to be proxied, what additional
* advices (e.g. AOP Alliance interceptors) and advisors to apply.
* @param beanClass the class of the bean to advise
* @param beanName the name of the bean
* @param customTargetSource the TargetSource returned by the
* {@link #getCustomTargetSource} method: may be ignored.
* Will be {@code null} if no custom target source is in use.
* @return an array of additional interceptors for the particular bean;
* or an empty array if no additional interceptors but just the common ones;
* or {@code null} if no proxy at all, not even with the common interceptors.
* See constants DO_NOT_PROXY and PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS.
* @throws BeansException in case of errors
* @see #DO_NOT_PROXY
* @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
*/
protected abstract Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException;
这个方法接受容器里产生的Bean的类及名称,以及Bean的原始对象。可以对Spring创建的Bean做代码判断,通过返回值告诉Spring是否要对这个Bean做动态代理。
Object数组返回值
可以返回DO_NOT_PROXY或PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS这两个常量,我们先看一下这两个常量的定义。
/**
* Convenience constant for subclasses: Return value for "do not proxy".
* @see #getAdvicesAndAdvisorsForBean
*/
protected static final Object[] DO_NOT_PROXY = null;
/**
* Convenience constant for subclasses: Return value for
* "proxy without additional interceptors, just the common ones".
* @see #getAdvicesAndAdvisorsForBean
*/
protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];
可以看到DO_NOT_PROXY是null,而PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS是一个空数组。
DO_NOT_PROXY比较好理解,就是对这个Bean不创建代理。
PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS的意思是不创建额外的代理。AbstractAutoProxyCreator有一个字段是interceptorNames,可以对这个字段设值,这里保存的是通用的interceptor的名字,如果返回值是空数组,Spring就会使用默认的代理。
private String[] interceptorNames = new String[0];
如果我们返回对象数据不是空的,那么返回值就作为额外的代理进行创建,也就是说,interceptorNames声明的代理会产生作用,返回值里的声明的代码也同样会产生作用。
创建代理过程
返回的对象数据需要是什么类型才会生效呢,interceptorNames是bean名称,根据bean名称去查找使用对应的切面类。最终在DefaultAdvisorAdapterRegistry的wrap方法里我们可以找到答案。
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
返回的对象数组,如果是MethodInterceptor、Advice会包装成DefaultPointcutAdvisor,最终以Advisor来实现代理。
关于MethodInterceptor、Advice、Advisor、Pointcut等Spring AOP的相关类,不在这里介绍,读者可以在其他地方找到并了解这些基本概念。
完整示例
public class MyProxyCreator extends AbstractAutoProxyCreator {
@Autowired
private MyAdvisor myAdvisor;
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException {
if ("singerService".equalsIgnoreCase(beanName)) {
return new Object[] { myAdvisor };
} else if (beanClass == SingerService.class) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
} else {
try {
if (customTargetSource.getTarget() instanceof SingerService) {
SingerService singerService = (SingerService) customTargetSource.getTarget();
if ("张三".equalsIgnoreCase(singerService.getName())) {
return new Object[] { myAdvisor };
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return DO_NOT_PROXY;
}
}
可以看到,AbstractAutoProxyCreator可以以非常灵活的方式去创建代理
0条评论