AOP 默认代理 模式

阅读本文大概需要 6.5 分钟。

来自:juejin.im/post/68449039

1. 从注解入手找到对应核心类

最近工作中我都是基于注解实现 AOP 功能,常用的开启 AOP 的注解是 @EnableAspectJAutoProxy,我们就从它入手。

上面的动图的流程的步骤就是:@EnableAspectJAutoProxy --> AspectJAutoProxyRegistrar -->AopConfigUtils .registerAspectJAnnotationAutoProxyCreatorIfNecessary -->AnnotationAwareAspectJAutoProxyCreator.class

AnnotationAwareAspectJAutoProxyCreator 查看其中文注释(如下),确定它就是 AOP 的核心类!-- 温安适 20191020

  1. AspectJAwareAdvisorAutoProxyCreator的子类 ,用于处理当前应用上下文中的注解切面
  2. 任何被AspectJ注解的类将自动被识别。
  3. 若SpringAOP代理模式可以识别,优先使用Spring代理模式。
  4. 它覆盖了方法执行连接点
  5. 如果使用aop:include元素, 则只有名称与include模式匹配的@aspectj bean才被视为切面 ,并由spring自动代理。
  6. Spring Advisors的处理请查阅,
org.springframework.aop
.framework.autoproxy.AbstractAdvisorAutoProxyCreator

@SuppressWarnings(“serial”)
public class AnnotationAwareAspectJAutoProxyCreator
extends AspectJAwareAdvisorAutoProxyCreator {
//…省略实现
}注解切面

虽然找到了核心类,但是并没有找到核心方法!下面我们尝试画类图确定核心方法。

2. 画核心类类图,猜测核心方法

AnnotationAwareAspectJAutoProxyCreator 的部分类图。



AnnotationAwareAspectJAutoProxyCreator 从类图看到了 AnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor,而 AOP 功能应该在创建完 Bean 之后执行,猜测 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization(实例化 bean 后处理)是核心方法。查看 AnnotationAwareAspectJAutoProxyCreator 实现的 postProcessAfterInitialization 方法,实际该方法在其父类 AbstractAutoProxyCreator 中。

//AbstractAutoProxyCreator中的postProcessAfterInitialization实现
@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;
}

发现发现疑似方法 wrapIfNecessary,查看其源码如下,发现 createProxy 方法。确定找对了地方。

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;
}
if (isInfrastructureClass(bean.getClass())
|| shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// 创建代理
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;
}

即 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization 方法,在该方法中由 wrapIfNecessary 实现了 AOP 的功能。wrapIfNecessary 中有 2 个和核心方法

  • getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器
  • createProxy 为当前 bean 创建代理 要想明白核心流程还需要分析这 2 个方法。

3. 读重点方法,理核心流程

3.1 getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器

查看源码如下,默认实现在 AbstractAdvisorAutoProxyCreator 中。

@Override
@Nullable
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();
}

查阅 findEligibleAdvisors 方法,就干了 3 件事

  • 找所有增强器,也就是所有 @Aspect 注解的 Bean
  • 找匹配的增强器,也就是根据 @Before,@After 等注解上的表达式,与当前 bean 进行匹配,暴露匹配上的。
  • 对匹配的增强器进行扩展和排序,就是按照 @Order 或者 PriorityOrdered 的 getOrder 的数据值进行排序,越小的越靠前。
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;
}

AnnotationAwareAspectJAutoProxyCreator 重写了 findCandidateAdvisors,下面我们看看具体实现了什么

3.1.1findCandidateAdvisors 找所有增强器,也就是所有 @Aspect 注解的 Bean

@Override
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) {
//@Aspect注解的类在这里除了
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}

从该方法我们可以看到 处理 @Aspect 注解的 bean 的方法是:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()。这个方法如下:

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<>();
//找到所有BeanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// 必须注意,bean会提前暴露,并被Spring容器缓存,但是这时还不能织入。
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
//找到所有被@Aspect注解的类
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析封装为Advisor返回
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;
}

这个方法可以概括为:

  • 找到所有 BeanName
  • 根据 BeanName 筛选出被 @Aspect 注解的类
  • 针对类中被 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 注解的方法,先按上边的注解顺序排序后按方法名称排序,每一个方法对应一个 Advisor。

3.2 createProxy 为当前 bean 创建代理。

3.2.1 创建代理的 2 种方式

众所周知,创建代理的常用的 2 种方式是:JDK 创建和 CGLIB,下面我们就看看这 2 中创建代理的例子。

3.2.1 .1 jdk 创建代理的例子

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxyMain {

public static void main(String\[\] args) {
    JDKProxyTestInterface target = new JDKProxyTestInterfaceImpl();
    // 根据目标对象创建代理对象
    JDKProxyTestInterface proxy =
     (JDKProxyTestInterface) Proxy
     .newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new JDKProxyTestInvocationHandler(target));
    // 调用代理对象方法
    proxy.testProxy();
}

interface JDKProxyTestInterface {
    void testProxy();
}
static class JDKProxyTestInterfaceImpl
                implements JDKProxyTestInterface {
    @Override
    public void testProxy() {
        System.out.println("testProxy");
    }
}

static class JDKProxyTestInvocationHandler
implements InvocationHandler {
private Object target;
public JDKProxyTestInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
System.out.println(“执行前”);
Object result= method.invoke(this.target,args);
System.out.println(“执行后”);
return result;
}
}

3.2.1 .2 cglib 创建代理的例子

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyTest {

static class CglibProxyService {
public CglibProxyService(){
}
void sayHello(){
System.out.println(" hello !");
}
}

static class CglibProxyInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object sub, Method method,
         Object\[\] objects, MethodProxy methodProxy)
                                      throws Throwable {
        System.out.println("before hello");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("after hello");
        return object;
    }
}

public static void main(String\[\] args) {
    // 通过CGLIB动态代理获取代理对象的过程
    Enhancer enhancer = new Enhancer();
    // 设置enhancer对象的父类
    enhancer.setSuperclass(CglibProxyService.class);
    // 设置enhancer的回调对象
    enhancer.setCallback(new CglibProxyInterceptor());
    // 创建代理对象
    CglibProxyService proxy= (CglibProxyService)enhancer.create();
    System.out.println(CglibProxyService.class);
    System.out.println(proxy.getClass());
    // 通过代理对象调用目标方法
    proxy.sayHello();
}

}

3.2.1 .3 jdk 创建代理与 cglib 创建代理的区别

3.2.2 Spring 如何选择的使用哪种方式

Spring 的选择选择如何代理时在 DefaultAopProxyFactory 中。

public class DefaultAopProxyFactory implements AopProxyFactory,
Serializable {
@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);
}
}
//…
}
  • config.isOptimize() 查看源码注释时发现,这个是配置使用 cglib 代理时,是否使用积极策略。
    这个值一般不建议使用!
  • config.isProxyTargetClass() 就是 @EnableAspectJAutoProxy 中的 proxyTargetClass 属性。


//exposeProxy=true AopContext 可以访问,proxyTargetClass=true CGLIB 生成代理 @EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)

  • hasNoUserSuppliedProxyInterfaces 是否存在可代理的接口

总结下 Spring 如何选择创建代理的方式:

  1. 如果设置了 proxyTargetClass=true,一定是 CGLIB 代理
  2. 如果 proxyTargetClass=false,目标对象实现了接口,走 JDK 代理
  3. 如果没有实现接口,走 CGLIB 代理

4. 总结

Spring 如何实现 AOP?,您可以这样说:

  1. AnnotationAwareAspectJAutoProxyCreator 是 AOP 核心处理类
  2. AnnotationAwareAspectJAutoProxyCreator 实现了 BeanProcessor,其中 postProcessAfterInitialization 是核心方法。
  3. 核心实现分为 2 步 getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器 createProxy 为当前 bean 创建代理
  4. getAdvicesAndAdvisorsForBean 核心逻辑如下 a. 找所有增强器,也就是所有 @Aspect 注解的 Bean b. 找匹配的增强器,也就是根据 @Before,@After 等注解上的表达式,与当前 bean 进行匹配,暴露匹配上的。c. 对匹配的增强器进行扩展和排序,就是按照 @Order 或者 PriorityOrdered 的 getOrder 的数据值进行排序,越小的越靠前。
  5. createProxy 有 2 种创建方法,JDK 代理或 CGLIB a. 如果设置了 proxyTargetClass=true,一定是 CGLIB 代理 b. 如果 proxyTargetClass=false,目标对象实现了接口,走 JDK 代理 c. 如果没有实现接口,走 CGLIB 代理。

    阅读本文大概需要 6.5 分钟。

    来自:juejin.im/post/68449039

    1. 从注解入手找到对应核心类

    最近工作中我都是基于注解实现 AOP 功能,常用的开启 AOP 的注解是 @EnableAspectJAutoProxy,我们就从它入手。

    上面的动图的流程的步骤就是:@EnableAspectJAutoProxy --> AspectJAutoProxyRegistrar -->AopConfigUtils .registerAspectJAnnotationAutoProxyCreatorIfNecessary -->AnnotationAwareAspectJAutoProxyCreator.class

    AnnotationAwareAspectJAutoProxyCreator 查看其中文注释(如下),确定它就是 AOP 的核心类!-- 温安适 20191020

    1. AspectJAwareAdvisorAutoProxyCreator的子类 ,用于处理当前应用上下文中的注解切面
    2. 任何被AspectJ注解的类将自动被识别。
    3. 若SpringAOP代理模式可以识别,优先使用Spring代理模式。
    4. 它覆盖了方法执行连接点
    5. 如果使用aop:include元素, 则只有名称与include模式匹配的@aspectj bean才被视为切面 ,并由spring自动代理。
    6. Spring Advisors的处理请查阅,
    org.springframework.aop
    .framework.autoproxy.AbstractAdvisorAutoProxyCreator

@SuppressWarnings(“serial”)
public class AnnotationAwareAspectJAutoProxyCreator
extends AspectJAwareAdvisorAutoProxyCreator {
//…省略实现
}注解切面

虽然找到了核心类,但是并没有找到核心方法!下面我们尝试画类图确定核心方法。

2. 画核心类类图,猜测核心方法

AnnotationAwareAspectJAutoProxyCreator 的部分类图。



AnnotationAwareAspectJAutoProxyCreator 从类图看到了 AnnotationAwareAspectJAutoProxyCreator 实现了 BeanPostProcessor,而 AOP 功能应该在创建完 Bean 之后执行,猜测 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization(实例化 bean 后处理)是核心方法。查看 AnnotationAwareAspectJAutoProxyCreator 实现的 postProcessAfterInitialization 方法,实际该方法在其父类 AbstractAutoProxyCreator 中。

//AbstractAutoProxyCreator中的postProcessAfterInitialization实现
@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;
}

发现发现疑似方法 wrapIfNecessary,查看其源码如下,发现 createProxy 方法。确定找对了地方。

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;
}
if (isInfrastructureClass(bean.getClass())
|| shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// 创建代理
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;
}

即 AnnotationAwareAspectJAutoProxyCreator 实现 BeanPostProcessor 的 postProcessAfterInitialization 方法,在该方法中由 wrapIfNecessary 实现了 AOP 的功能。wrapIfNecessary 中有 2 个和核心方法

  • getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器
  • createProxy 为当前 bean 创建代理 要想明白核心流程还需要分析这 2 个方法。

3. 读重点方法,理核心流程

3.1 getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器

查看源码如下,默认实现在 AbstractAdvisorAutoProxyCreator 中。

@Override
@Nullable
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();
}

查阅 findEligibleAdvisors 方法,就干了 3 件事

  • 找所有增强器,也就是所有 @Aspect 注解的 Bean
  • 找匹配的增强器,也就是根据 @Before,@After 等注解上的表达式,与当前 bean 进行匹配,暴露匹配上的。
  • 对匹配的增强器进行扩展和排序,就是按照 @Order 或者 PriorityOrdered 的 getOrder 的数据值进行排序,越小的越靠前。
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;
}

AnnotationAwareAspectJAutoProxyCreator 重写了 findCandidateAdvisors,下面我们看看具体实现了什么

3.1.1findCandidateAdvisors 找所有增强器,也就是所有 @Aspect 注解的 Bean

@Override
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) {
//@Aspect注解的类在这里除了
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}

从该方法我们可以看到 处理 @Aspect 注解的 bean 的方法是:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()。这个方法如下:

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<>();
//找到所有BeanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// 必须注意,bean会提前暴露,并被Spring容器缓存,但是这时还不能织入。
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
//找到所有被@Aspect注解的类
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析封装为Advisor返回
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;
}

这个方法可以概括为:

  • 找到所有 BeanName
  • 根据 BeanName 筛选出被 @Aspect 注解的类
  • 针对类中被 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 注解的方法,先按上边的注解顺序排序后按方法名称排序,每一个方法对应一个 Advisor。

3.2 createProxy 为当前 bean 创建代理。

3.2.1 创建代理的 2 种方式

众所周知,创建代理的常用的 2 种方式是:JDK 创建和 CGLIB,下面我们就看看这 2 中创建代理的例子。

3.2.1 .1 jdk 创建代理的例子

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxyMain {

public static void main(String\[\] args) {
    JDKProxyTestInterface target = new JDKProxyTestInterfaceImpl();
    // 根据目标对象创建代理对象
    JDKProxyTestInterface proxy =
     (JDKProxyTestInterface) Proxy
     .newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new JDKProxyTestInvocationHandler(target));
    // 调用代理对象方法
    proxy.testProxy();
}

interface JDKProxyTestInterface {
    void testProxy();
}
static class JDKProxyTestInterfaceImpl
                implements JDKProxyTestInterface {
    @Override
    public void testProxy() {
        System.out.println("testProxy");
    }
}

static class JDKProxyTestInvocationHandler
implements InvocationHandler {
private Object target;
public JDKProxyTestInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
System.out.println(“执行前”);
Object result= method.invoke(this.target,args);
System.out.println(“执行后”);
return result;
}
}

3.2.1 .2 cglib 创建代理的例子

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyTest {

static class CglibProxyService {
public CglibProxyService(){
}
void sayHello(){
System.out.println(" hello !");
}
}

static class CglibProxyInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object sub, Method method,
         Object\[\] objects, MethodProxy methodProxy)
                                      throws Throwable {
        System.out.println("before hello");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("after hello");
        return object;
    }
}

public static void main(String\[\] args) {
    // 通过CGLIB动态代理获取代理对象的过程
    Enhancer enhancer = new Enhancer();
    // 设置enhancer对象的父类
    enhancer.setSuperclass(CglibProxyService.class);
    // 设置enhancer的回调对象
    enhancer.setCallback(new CglibProxyInterceptor());
    // 创建代理对象
    CglibProxyService proxy= (CglibProxyService)enhancer.create();
    System.out.println(CglibProxyService.class);
    System.out.println(proxy.getClass());
    // 通过代理对象调用目标方法
    proxy.sayHello();
}

}

3.2.1 .3 jdk 创建代理与 cglib 创建代理的区别

3.2.2 Spring 如何选择的使用哪种方式

Spring 的选择选择如何代理时在 DefaultAopProxyFactory 中。

public class DefaultAopProxyFactory implements AopProxyFactory,
Serializable {
@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);
}
}
//…
}
  • config.isOptimize() 查看源码注释时发现,这个是配置使用 cglib 代理时,是否使用积极策略。
    这个值一般不建议使用!
  • config.isProxyTargetClass() 就是 @EnableAspectJAutoProxy 中的 proxyTargetClass 属性。


//exposeProxy=true AopContext 可以访问,proxyTargetClass=true CGLIB 生成代理 @EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)

  • hasNoUserSuppliedProxyInterfaces 是否存在可代理的接口

总结下 Spring 如何选择创建代理的方式:

  1. 如果设置了 proxyTargetClass=true,一定是 CGLIB 代理
  2. 如果 proxyTargetClass=false,目标对象实现了接口,走 JDK 代理
  3. 如果没有实现接口,走 CGLIB 代理

4. 总结

Spring 如何实现 AOP?,您可以这样说:

  1. AnnotationAwareAspectJAutoProxyCreator 是 AOP 核心处理类
  2. AnnotationAwareAspectJAutoProxyCreator 实现了 BeanProcessor,其中 postProcessAfterInitialization 是核心方法。
  3. 核心实现分为 2 步 getAdvicesAndAdvisorsForBean 获取当前 bean 匹配的增强器 createProxy 为当前 bean 创建代理
  4. getAdvicesAndAdvisorsForBean 核心逻辑如下 a. 找所有增强器,也就是所有 @Aspect 注解的 Bean b. 找匹配的增强器,也就是根据 @Before,@After 等注解上的表达式,与当前 bean 进行匹配,暴露匹配上的。c. 对匹配的增强器进行扩展和排序,就是按照 @Order 或者 PriorityOrdered 的 getOrder 的数据值进行排序,越小的越靠前。
  5. createProxy 有 2 种创建方法,JDK 代理或 CGLIB a. 如果设置了 proxyTargetClass=true,一定是 CGLIB 代理@EnableAspectJAutoProxy(proxyTargetClass = true)// true 默认 为 cglib代理 b. 如果 proxyTargetClass=false,目标对象实现了接口,走 JDK 代理 c. 如果没有实现接口,走 CGLIB 代理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值