Spring框架AOP源码分析
1.写在前面
做java开发的不可能不适用spring框架,我们都知道spring框架的两个基础功能就是Ioc和aop,相比来说Ioc会应用的更广泛一些,但aop同样重要,今天就来详细分析一下spring的aop的实现原理,会深入spring源码级别,对于spring不太熟悉的同学来说可能有点难,没有办法,分析源码就是这样,需要对框架有一定的应用经验并且比较熟悉原理,毕竟一个成熟的框架,特别是像spring这样的java技术栈统治级的框架。如果想学习spring的基本功能推荐几篇文章。
另外这篇源码分析也是干货满满。
好,我们开始今天的主题,首先搭建一个基本的spring环境,本案例是基于注解分析的。
2.环境搭建
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.6</version>
</dependency>
</dependencies>
创建一个启动配置类,这是一个空配置类,仅仅为了启动加载。@EnableAspectJAutoProxy注解表示使能了基于AspectJ的AOP的功能
@Configuration
@ComponentScan(basePackages = {"com.li.study"})
@EnableAspectJAutoProxy
public class AppConfig {
}
创建两个bean,一个是普通的bean,另一个是用于AOP功能用于定义切点,通知的bean
@Component
public class CommonBean {
public void test(){
System.out.println("勤能补拙");
}
}
@Component
@Aspect
public class AspectBean {
@Pointcut("execution(* com.li.study.bean.CommonBean.*(..))")
public void pointcut(){};
@Before("pointcut()")
public void before(){
System.out.println("before");
}
@After("pointcut()")
public void after(){
System.out.println("after");
}
@Around("pointcut()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("xxxx");
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("oooo");
}
}
最后创建一个启动类
public class TestBean {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CommonBean bean = context.getBean(CommonBean.class);
bean.test();
}
}
最后启动main方法,执行结果如下
xxxx
before
勤能补拙
after
oooo
这就是一个简单的AOP测试案例,为了让大家熟悉AOP是什么,这里不太想说明具体什么是AOP,因为这个很难几句话说明白,大家可以对比面向对象来理解,这个叫面向切面,它是一种横向的扩展,总之只可意会不可言传,我相信你是理解AOP的,不然也不会看到这里,如果您不知道什么是AOP和OOP,那。。。慢走不送,出门左转。
3.源码分析
3.1 @EnableAspectJAutoProxy注解
在配置类上添加@EnableAspectJAutoProxy注解就打开了基于AspectJ的动态代理功能,那么为什么呢?怎么实现的呢?我们来看一下。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
我们看到这个注解上添加了一个@Import(AspectJAutoProxyRegistrar.class)注解,就是这个注解实现类基于AspectJ的动态代理功能,这个@Import注解很强大,
他可以将对象注入到Spring容器中,具体的实现原理请参考@Import注解详细分析,这里不详细分析了,这篇文章写的很清楚。我们直接进入AspectJAutoProxyRegistrar类。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
这个类实现了ImportBeanDefinitionRegistrar接口,通过@Improt注解传入实现ImportBeanDefinitionRegistrar接口的类,在创建容器的时候会调用接口的registerBeanDefinitions方法,这是@Import注解的一种用法。
我们来看具体的方法实现,主要关注方法的第一行代码。从方法名上来看,是注册名字是AspectJAnnotationAutoProxyCreator的类的对象到容器中。
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
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;
}
上面的代码实际上就是注册了一个类型为AnnotationAwareAspectJAutoProxyCreator的bean到容器中,其实这就是@EnableAspectJAutoProxy注解主要实现的功能。
3.2 AnnotationAwareAspectJAutoProxyCreator
先来看一下继承结构
通过上图可以看出,AnnotationAwareAspectJAutoProxyCreator间接实现类BeanPostProcessor接口,是一个后置处理器。spring的后置处理器的学习请移步BeanPostProcessor后置处理器原理与应用
既然是后置处理器我们主要关注BeanPostProcessor接口定义的方法。
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
通过方法的名字也能看出来,这两个方法一个是在bean初始化前执行,一个是在初始化后执行。重写这两个方法的类是AbstractAutoProxyCreator,我们这两个方法的实现。
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return 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(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName); //获取key,根据beanName是不是空以及是不是工厂bean来确定key
//earlyProxyReferences集合不包含当前bean,成立,这个判断与在bean实例化之前被代理有关,要实现实例化之前被代理需要其他配置,
//在本案例中没有配置,所以会执行到if语句内部代码
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
初始化之前执行的方法没做什么处理,我们关注初始化之后的逻辑。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//beanName不是空并且在实例化时候已经被缓存到targetSourcedBeans,已经在是实例化是被代理
//不需要实例化完成后处理了
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//缓存中存在被代理完成的对象,返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//特殊的类不进行动态代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //查找当前bean的所有通知
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;
}
3.3 查找增强
这里说的增强包括Advice和Advisor,查找的方法在AbstractAdvisorAutoProxyCreator类
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable 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;
}
这里主要分为两个步骤:查找所有增强,在所有增强中找到匹配当前类型的
3.3.1 查找全部增强
注意这个查找所有增强的方法在AnnotationAwareAspectJAutoProxyCreator中,在这个方法中会调用父类的findCandidateAdvisors方法。
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
3.3.1.1 父类查找增强的方法
我们先去看一下父类的这个方法的实现,在AbstractAdvisorAutoProxyCreator类中
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
继续向下看查找的方法实现
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
这个方法逻辑比较清晰,都是一样的套路,先看有没有缓存,没有的话再去查找所有实现Advisor的beanName,然后将结果缓存起来,最后遍历beanName集合找到容器中的所有Advisor实现类,并返回。
3.3.1.2 当前类查找增强的方法
当前类中其实包含了解析AspectJ相关的注解的。
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName, false);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); //读取切点信息
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
- 这个方法的前一部分实现类与父类中查找增强的逻辑,这里我没搞清楚为什么又查找一遍,明明已经在上面执行了父类相同的逻辑,希望明白其中原理的大佬指点,不胜感激
- 接下来判断当前bean是否有@Aspect注解,如果存在的话会去解析@Pointcut注解,获取切点信息,然后根据是不是单例的将增强缓存到不同的集合中
- 最后将获取的增强返回
至此,所有的增强已经获取完成并缓存,接下来开始找到匹配当前bean的增强
3.4 查找匹配的增强
我们回到AbstractAdvisorAutoProxyCreator类的findEligibleAdvisors方法的第二行代码继续分析。
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
第一行和最后一行做了一个正在代理的一个标记,我们看中间的代码
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
这个方法先遍历所有的增强,如果是IntroductionAdvisor的实现类,并且可以应用到当前的bean,加入到结合。
IntroductionAdvisor是Advisor的子接口,增加了过滤和验证的方法,主要作用还是Advisor。我们来看匹配增强的方法canApply
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
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;
}
}
这里显示判断IntroductionAdvisor接口,然后执行过滤,然后继续执行canApply方法
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
//如果所有的类都可以应用此增强,没必要继续向下执行了
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
//如果已经是被代理的对象了,不需要再被代理了
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
//获取当前bean的所有包括子类的方法对象,注意这里有些误导,不只是获取了接口方法对象
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
//查找匹配的方法,通过AspectJ的表达式来匹配的
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
上面的代码写了注释,先做一些判断,如果匹配所有的增强就不向下执行了,已经是代理对象的就不再匹配了,然后获取当前类及其子类的所有方法对象,这里是所有方法不只是接口方法,遍历执行匹配逻辑。
到目前位置获取了所有匹配的增强,接下来就是执行更具增强执行代理逻辑了。
3.5 创建代理对象
我们回到查找增强的方法的下面继续阅读,位置在AbstractAutoProxyCreator类的wrapIfNecessary方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 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 proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable 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());
}
这个方法一个重要的事情是创建了一个代理工厂类,然后将增强集合以及目标代理类保存到代理工厂中。真正创建代理对象的再左后一行代码。我们进入代理工厂的getProxy方法。
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
这个他先创建一个AopProxy对象,我们看一下实现逻辑。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
这里他先获取了AopProxy的工厂,这个AopProxy工厂实际的实现类是DefaultAopProxyFactory。接下来就是去这个工厂获取AopProxy对象。
3.5.1 通过工厂方法获取AopProxy对象
这个createAopProxy是AopProxyFactory的接口方法,DefaultAopProxyFactory实现了AopProxyFactory接口。
这里的思路不知道大家看出来没有,这是一个标准的工厂方法模式,通过接口获取对象,如果我们不想利用AopProxy对象来实现动态代理,可以自定义一个实现AopProxyFactory接口的类,提供自定义的AopProxy实现来完成相应的扩展。
来看DefaultAopProxyFactory实现的createAopProxy方法。
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);
}
}
这里的逻辑可能大家一看就觉得熟悉,这就是常说的JDK的动态代理和Cglib的动态代理两种方式。
如果目标对象实现了接口或者本身就是代理对象,那么使用JDK的动态代理,否则使用Cglib动态代理。
3.5.2 JDK动态代理
不管是JDK的动态代理还是Cglib动态代理都实现了AopProxy接口,我们先来看JDK动态代理的getProxy方法
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
其实这里没什么可以多说的,就是JDK动态代理的原理,我们自己应用JDK的动态代理功能也是这样做的。
- 先获取要代理的接口方法
- 创建InvocationHandler接口实现对象
- 创建代理对象
这里的JdkDynamicAopProxy类同时实现来InvocationHandler接口,创建代理对象时传入的是this,这里的细节跳过了。
3.5.3 Cglib动态代理
Cglib是一个常用的代码生成技术,在很多框架中都有应用,他是对字节码操作的,很底层,本人理解的不是很充分,这里也不误导大家了。