1、准备工作
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="org.spring.aop" />
<aop:aspectj-autoproxy/>
</beans>
@Component
public class UserServiceImpl implements UserService{
public void createa() {
System.out.println("userServiceImpl a");
}
}
@Aspect
@Component
public class AnnotationAop {
@Before("execution(* org.spring.aop.UserServiceImpl.*(..))")
public void before() {
System.out.println("---- 发法执行前-----");
}
@After("execution(* org.spring.aop.UserServiceImpl.*(..))")
public void after() {
System.out.println("---- 发法执行后-----");
}
---- 发法执行前-----
userServiceImpl a
---- 发法执行后-----
我们知道,aspectj静态织入,aspectJ在进行aop时,是在编译时就植入代码到class文件,而spring是通过动态代理实现aop,spring是如何利用aspectj做动态代理的呢?
2、流程分析
先来查看xml中aop:aspectj-autoproxy的作用
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
在refresh()方法中初步扫描bean定义,并且返回bean工厂
AopConfigUtils类
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
至此,aop:aspectj-autoproxy是为了在bean工厂中添加beanName为internalAutoProxyCreator的bean定义,class org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator的继承关系图
该类实现了BeanPostProcessor、InstantiationAwareBeanPostProcessor接口,我们知道BeanPostProcessor、InstantiationAwareBeanPostProcessor接口的方法都是对spring bean对象的扩展
首先看InstantiationAwareBeanPostProcessor接口方法的执行
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// advisedBean集合中包括不需要的aop代理的bean,比如是aspect切面类或者普通类
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// isInfrastructureClass(beanClass) 是否是Advice、Pointcut等接口的实现类
// shouldSkip(beanClass, beanName) 封装所有的before、around等注解封装为Advisor对象
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.
// 如果是自定义TargetSource,创建代理
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
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;
}
// 在进行aop代理之前,会先获取到所有的Advisor,不仅是实现了Advisor接口,还包括Aspject的before、around注解等也会封装为Advisor备用
// 到此也基本得知,spring利用了aspectj的注解来实现动态代理,只是利用了注解,并未利用其静态织入功能
BeanPostProcessor postProcessAfterInitialization接口的实现(创建aop代理类)
为什么是后置处理来实现aop代理对象的创建?个人理解,如果使用前置处理来创建代理对象不太符合bean生命周期的全流程规范,一个原始bean尚未创建完成就对其进行了代理
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 如果目标类是一个切面类,不能进行aop代理,返回原始bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果目标类是一个切面类,不能进行aop代理,返回原始bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 获取所有模板类的通知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;
}
// jdk动态代理和cglib动态代理的选择
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// isOptimize设置为true
// config.isProxyTargetClass() proxyTargetClass为true
// hasNoUserSuppliedProxyInterfaces(config) 没有指定代理接口
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) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
总结
spring利用的只是aspectj的注解,生成Advisor,再通过bean的后置处理创建bean的代理对象。
spring在jdk动态代理和cglib动态代理的选择中,会根据条件优先选择使用jdk动态代理。