spring 对于aop编程进行了抽象
本片文章讨论aop在spring里的处理流程;
首先编写代码
- 编写增强类
/**
* 声明切入点和增强类
*/
@Component
@Aspect
public class AspectJTest {
/**
* 定义增强切入点
*/
@Pointcut("execution(* *.test(..))")
public void test(){
}
/**
* 前置增强
*/
@Before("test()")
public void beforeTest(){
System.out.println("before test");
}
/**
* 后置增强
*/
@After("test()")
public void afterTest(){
System.out.println("after test");
}
}
- 被增强类
@Component
public class TestBean {
public void test(){
System.out.println("test print....");
}
}
- 启动类
@ComponentScan
// 开启aop
@EnableAspectJAutoProxy
public class AnnotationAopTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationAopTest.class);
TestBean testBean = applicationContext.getBean(TestBean.class);
testBean.test();
}
}
调试spring代码,关键类和方法
AbstractAutoProxyCreator 类,该类是SmartInstantiationAwareBeanPostProcessor实现,就是说在bean的实例化前,初始化前,初始化后三个过程都会触发该类的方法。
其中有两个方法会根据条件触发是否生成代理
- postProcessBeforeInstantiation 方法, 在bean实例化前触发,如果此时bean已经被其他方式完成了初始化,则在此进行代理判断.
@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) {
// 获取自定义原始对象
// 这里相当于提供一个机会给 用户自己定义被代理对象的实例化过程
// 否在被代理对象将在spring容器初始化完成后在被代理
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);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
- postProcessAfterInitialization 方法,在bean初始化完成后触发。在这里spring对bean对象进行了包装
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 判断是否是spring内部aop类, 或者定义需要跳过的类
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 根据bean查询增强点
// 方式是遍历beanFactory的所有bean,如果是AspectJ类型则存储下来.
// 后根据切入点是否匹配进行过滤, 如果过滤后还有匹配的数据则创建代理
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 存在增强点,根据增强点生成代理对象
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
关键就是Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 根据bean类查找有无对应的增强点
/**
* Find all eligible Advisors for auto-proxying this class.
* @param beanClass the clazz to find advisors for
* @param beanName the name of the currently proxied bean
* @return the empty List, not {@code null},
* if there are no pointcuts or interceptors
* @see #findCandidateAdvisors
* @see #sortAdvisors
* @see #extendAdvisors
*/
protected List findEligibleAdvisors(Class> beanClass, String beanName) {
// 查询出所有的增强点
List candidateAdvisors = findCandidateAdvisors();
// 匹配增强点和beanClass是否匹配
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 根据order排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
查找出增强点,并根据order排序;
根据增强点集合,生成代理工厂对象, 代理工厂根据配置生成真实代理类
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(
Class> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
// 暴露代理对象
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 判断是类代理还是接口代理
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 创建增强链
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 保存关联的原始被代理对象
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
最终代理的创建委托到 DefaultAopProxyFactory类的createAopProxy方法
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 判断是否有强制优化,或类代理
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
整个创建代理的流程就算完成了。
总结
总结一下,spring aop 没有在beanDefinition里指定bean是不是需要代理. 而是在bean真正实例化前或者初始化完成后,通过BeanPostProcessor查询当前bean有无增强点,有则进行代理。
被代理对象(targetSource)可以自定义,也可以是spring容器初始化;
只要创建TargetSource对象,并向AbstractAutoProxyCreator注册,即可以自定义被代理对象.