spring AbstractBeanDefinition创建bean类型是动态代理类的方式

简介:

v1.接口 Class<?> resourceClass

v2.获取builder

BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(resourceClass);

v3.获取接口对应的动态代理class

Class<?> targetProxyClass = Proxy.getProxyClass(XXX.class.getClassLoader(), new Class[]{resourceClass});

v4.targetProxyClass构造参数类型 InvocationHandler,通过builder设置

   builder.addConstructorArgValue(Proxy.getInvocationHandler(xxxProxyBean) 或者 new InvocationHandler(){...});

 AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

   beanDefinition.setBeanClass(targetProxyClass);

   registry.registerBeanDefinition("beanName", beanDefinition);

 

v5.记录一下自己曾经写的一个例子

v5.1 抽象类ProxyFactoryBean

复制代码
package com.hjzgg.apigateway.soa.proxy;

import com.hjzgg.apigateway.soa.exceptions.SoaException;
import com.hjzgg.apigateway.soa.proxy.consumer.ConsumerProxyFactoryBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by hujunzheng on 2017/7/7.
 */
public abstract class ProxyFactoryBean implements FactoryBean {

    protected Class<?> selfDynamicProxyClass;//代理类
    protected Class<?> resourceClass;//接口类
    protected String version;//dubbo 版本
    protected String group;//dubbo 分组
    protected Object proxy;//代理对象
    protected Method createProxyMethod;

    public ProxyFactoryBean(Class<?> selfDynamicProxyClass, Class<?> resourceClass, String version, String group) throws SoaException {
        if (Objects.isNull(selfDynamicProxyClass)) {
            throw new SoaException("selfDynamicProxyClass 动态代理类不能为null");
        }
        try {
            this.createProxyMethod = Stream.of(selfDynamicProxyClass.getMethods())
                    .filter(method -> Modifier.isStatic(method.getModifiers())
                            && Modifier.isPublic(method.getModifiers())
                            && !Modifier.isAbstract(method.getModifiers())
                            && method.getParameters().length == 2
                            && method.getParameters()[0].getType().equals(ProxyFactoryBean.class)
                            && method.getParameters()[1].getType().equals(Class.class)
                            && !method.getReturnType().equals(void.class))
                    .collect(Collectors.toList())
                    .get(0);
        } catch (Exception e) {
            throw new SoaException("500", String.format("%s %s %s和%s %s, %s %s"
                    , ClassUtils.getQualifiedName(selfDynamicProxyClass)
                    , " 没有参数类型是 "
                    , ClassUtils.getQualifiedName(ConsumerProxyFactoryBean.class)
                    , ClassUtils.getQualifiedName(Class.class)
                    , " 的、公共的、非抽象的、返回值非void的方法"
                    , "请将你的动态代理类继承"
                    , ClassUtils.getQualifiedName(DynamicProxyAdapter.class)
            ), e);
        }

        this.selfDynamicProxyClass = selfDynamicProxyClass;
        this.resourceClass = resourceClass;
        this.version = version;
        this.group = group;
    }

    protected Object newInstance() throws SoaException {
        if(this.isSingleton() && this.proxy != null) {
            return proxy;
        }
        synchronized (this) {
            Object target;
            try {
                target = this.createProxyMethod.invoke(null,this, selfDynamicProxyClass);
            } catch (Exception e) {
                throw new SoaException("500", String.format("%s %s %s"
                        , ClassUtils.getQualifiedName(selfDynamicProxyClass)
                        , createProxyMethod.getName()
                        , "创建代理类异常")
                        , e);
            }
            if(proxy == null) {
                proxy = target;
            }
            return target;
        }
    }

    public Class<?> getSelfDynamicProxyClass() {
        return selfDynamicProxyClass;
    }

    public void setSelfDynamicProxyClass(Class<?> selfDynamicProxyClass) {
        this.selfDynamicProxyClass = selfDynamicProxyClass;
    }

    public Class<?> getResourceClass() {
        return resourceClass;
    }

    public void setResourceClass(Class<?> resourceClass) {
        this.resourceClass = resourceClass;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }
}
复制代码

v5.2 ProxyFactoryBean具体实现类ProviderProxyFactoryBean

复制代码
package com.hjzgg.apigateway.soa.proxy.provider;

import com.hjzgg.apigateway.soa.exceptions.SoaException;
import com.hjzgg.apigateway.soa.proxy.ProxyFactoryBean;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;

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

/**
 * @author hujunzheng
 * @create 2018-02-18 下午3:01
 **/
public class ProviderProxyFactoryBean extends ProxyFactoryBean {
    public ProviderProxyFactoryBean(Class<?> selfDynamicProxyClass, Class<?> resourceClass, String version, String group) throws SoaException {
        super(selfDynamicProxyClass, resourceClass, version, group);
    }

    @Override
    public Object getObject() throws Exception {
        return this.newInstance();
    }

    @Override
    public Class<?> getObjectType() {
        return resourceClass;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    public static Class<?> getProxyClass(Class<?> resourceClass) {
        /**
         * @see com.hjzgg.apigateway.dubbo.configure.SelfDubboAnnotationBean#postProcessAfterInitialization(Object, String)
         * @see org.springframework.aop.support.AopUtils#isAopProxy(Object)
         * @see org.springframework.aop.support.AopUtils#getTargetClass(Object)
         * @see com.hjzgg.apigateway.soa.proxy.provider.ProviderDynamicProxy#invoke(Object, Method, Object[])
         * */
        return Proxy.getProxyClass(ProviderProxyFactoryBean.class.getClassLoader(), new Class[]{resourceClass, SpringProxy.class, TargetClassAware.class});
    }
}
复制代码

v5.3 动态代理适配器DynamicProxyAdapter

复制代码
package com.hjzgg.apigateway.soa.proxy;

import com.hjzgg.apigateway.soa.exceptions.SoaException;
import org.springframework.util.ClassUtils;

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

/**
 * @author hujunzheng
 * @create 2018-02-04 上午12:00
 **/
public class DynamicProxyAdapter implements InvocationHandler {
    public DynamicProxyAdapter(ProxyFactoryBean factoryBean) {
        this.bean = factoryBean;
    }

    protected ProxyFactoryBean bean;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        throw new SoaException(String.format("%s %s %s", "你应当重写", ClassUtils.getQualifiedName(DynamicProxyAdapter.class), "invoke方法"));
    }

    public static Object createJDKProxy(ProxyFactoryBean factoryBean, Class<?> selfDynamicProxyClass) throws SoaException {
        if (!DynamicProxyAdapter.class.equals(selfDynamicProxyClass.getSuperclass())) {
            throw new SoaException(String.format("%s %s %s"
                    , ClassUtils.getQualifiedName(selfDynamicProxyClass)
                    , "需要继承"
                    , ClassUtils.getQualifiedName(DynamicProxyAdapter.class)
            ));
        }
        Object selfDynamicProxyInstance;
        try {
            selfDynamicProxyInstance = selfDynamicProxyClass.getConstructor(factoryBean.getClass()).newInstance(factoryBean);
        } catch (Exception e) {
            throw new SoaException("500", "动态代理类创建失败", e);
        }
        Object proxy = Proxy.newProxyInstance(selfDynamicProxyClass.getClassLoader(),
                new Class[]{factoryBean.getResourceClass()}, (InvocationHandler) selfDynamicProxyInstance);
        return proxy;
    }
}
复制代码

v5.4 继承DynamicProxyAdapter 实现invoke接口 ProviderDynamicProxy

复制代码
package com.hjzgg.apigateway.soa.proxy.provider;

import com.hjzgg.apigateway.commons.utils.ContextUtils;
import com.hjzgg.apigateway.soa.annotation.SOAImplements;
import com.hjzgg.apigateway.soa.exceptions.SoaException;
import com.hjzgg.apigateway.soa.proxy.DynamicProxyAdapter;
import com.hjzgg.apigateway.soa.proxy.consumer.ConsumerProxyFactoryBean;
import org.springframework.aop.TargetClassAware;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

public class ProviderDynamicProxy extends DynamicProxyAdapter {

    private static final ConcurrentHashMap<Class<?>, Object> map = new ConcurrentHashMap<>();

    public ProviderDynamicProxy(ProviderProxyFactoryBean factoryBean) {
        super(factoryBean);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            if (method.equals(TargetClassAware.class.getMethod("getTargetClass", new Class[]{}))) {
                return bean.getResourceClass();
            }
            return method.invoke(this.findRelevantServiceProvider(), args);
        } catch (Exception e) {
            throw new SoaException("500", String.format("%s %s %s"
                    , "invoke service proxy object error!"
                    , ClassUtils.getQualifiedName(this.bean.getResourceClass())
                    , method.getName()
            ), e);
        }
    }

    private Object findRelevantServiceProvider() throws SoaException {
        Class<?> resourceClass = super.bean.getResourceClass();

        if (!map.contains(resourceClass)) {
            Stream<?> stream = ContextUtils.getBeans(SOAImplements.class)
                    .stream()
                    .filter(serviceProvider -> resourceClass.isAssignableFrom(serviceProvider.getClass()));
            if (stream.count() > 1) {
                throw new SoaException(String.format(
                        "multiple relevant service provider found with annotation %s and interface is %s"
                        , ClassUtils.getQualifiedName(SOAImplements.class)
                        , ClassUtils.getQualifiedName(resourceClass))
                );
            }

            if (stream.count() == 1) {
                map.put(resourceClass, stream.findFirst().get());
            } else {
                List<?> objects = ContextUtils.getBeans(SOAImplements.class);
                if (objects.size() > 1) {
                    throw new SoaException(String.format(
                            "multiple relevant service provider found with annotation %s"
                            , ClassUtils.getQualifiedName(SOAImplements.class))
                    );
                }

                if (objects.size() == 1) {
                    map.put(resourceClass, objects.get(0));
                } else {
                    try {
                        Object object = ContextUtils.getBean(resourceClass);
                        map.put(resourceClass, object);
                    } catch (Exception e) {
                        throw new SoaException("500", String.format(
                                "find relevant service provider with interface %s error"
                                , ClassUtils.getQualifiedName(resourceClass)), e
                        );
                    }
                }
            }
        }

        return map.get(resourceClass);
    }
}
复制代码

v5.5 注册类型是jdk proxy类型的bean

复制代码
//参数dynamicProxyClass 是 ProviderDynamicProxy
public static boolean registerProvider(BeanDefinitionRegistry registry, Class<?> dynamicProxyClass, Class<?> resourceClass) {
    String apiClassInfo = ClassUtils.getQualifiedName(resourceClass);
    try {
        /**
         * 通过代理bean的方式创建创建 服务bean
         * @see com.hjzgg.apigateway.dubbo.configure.SelfDubboAnnotationBean#postProcessAfterInitialization(Object, String)
         * if (AopUtils.isAopProxy(bean)), 判断bean的类型如果是代理类型,进行dubbo注解解析处理
         * */
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(resourceClass);
        String dubboVersion = resourceClass.getAnnotation(Service.class).version();
        String dubboGroup = resourceClass.getAnnotation(Service.class).group();
        ProviderProxyFactoryBean providerProxyFactoryBean = new ProviderProxyFactoryBean(dynamicProxyClass, resourceClass, dubboVersion, dubboGroup);
        /**
         * providerProxyFactoryBean.getObject() 得到的是通过 Proxy.newInstance方法获取到的代理类
         * @see com.hjzgg.apigateway.soa.proxy.DynamicProxyAdapter#createJDKProxy(ProxyFactoryBean, Class)
         * 可通过 Proxy.getInvocationHandler方法拿到 InvocationHandler实例
         */
        Class<?> targetProxyClass = ProviderProxyFactoryBean.getProxyClass(resourceClass);
        builder.addConstructorArgValue(Proxy.getInvocationHandler(providerProxyFactoryBean.getObject()));
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        beanDefinition.setBeanClass(targetProxyClass);

        beanDefinition.setAttribute(Constants.API_CLASS_INFO, resourceClass);
        String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
        if (registry.containsBeanDefinition(beanName)) {
            log.debug(beanName + " already exists! Class is " + apiClassInfo + " .");
            return false;
        }
        registry.registerBeanDefinition(beanName, beanDefinition);
        return true;
    } catch (Exception e) {
        log.error("registerProvider proxy bean error! Class is " + apiClassInfo + " .");
        return false;
    }
}
复制代码

v5.6 附加SelfDubboAnnotationBean

  View Code

v 5.7 附加AopUtils相关方法

复制代码
/**
 * Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
 * <p>This method additionally checks if the given object is an instance
 * of {@link SpringProxy}.
 * @param object the object to check
 * @see #isJdkDynamicProxy
 * @see #isCglibProxy
 */
public static boolean isAopProxy(Object object) {
    return (object instanceof SpringProxy &&
            (Proxy.isProxyClass(object.getClass()) || ClassUtils.isCglibProxyClass(object.getClass())));
}


/**
 * Determine the target class of the given bean instance which might be an AOP proxy.
 * <p>Returns the target class for an AOP proxy or the plain class otherwise.
 * @param candidate the instance to check (might be an AOP proxy)
 * @return the target class (or the plain class of the given object as fallback;
 * never {@code null})
 * @see org.springframework.aop.TargetClassAware#getTargetClass()
 * @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass(Object)
 */
public static Class<?> getTargetClass(Object candidate) {
    Assert.notNull(candidate, "Candidate object must not be null");
    Class<?> result = null;
    if (candidate instanceof TargetClassAware) {
        result = ((TargetClassAware) candidate).getTargetClass();
    }
    if (result == null) {
        result = (isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
    }
    return result;
}
复制代码









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/8527338.html,如需转载请自行联系原作者
目录
相关文章
|
25天前
|
缓存 Java Spring
Spring 框架中 Bean 的生命周期
Spring 框架中 Bean 的生命周期
32 1
|
30天前
|
XML 存储 Java
Spring重要类解析
Spring重要类解析
20 0
|
1月前
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
61 0
|
1月前
|
监控 Java 开发者
Spring AOP动态代理
Spring AOP动态代理
43 1
|
1月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
1月前
|
存储 NoSQL Java
Spring Boot统计一个Bean中方法的调用次数
Spring Boot统计一个Bean中方法的调用次数
35 1
|
1天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
9天前
|
Java 数据库连接 开发者
浅谈Spring的Bean生命周期
浅谈Spring的Bean生命周期
18 1
|
13天前
|
监控 Java 数据库连接
Spring高手之路17——动态代理的艺术与实践
本文深入分析了JDK和CGLIB两种动态代理技术在Spring框架中的应用。讨论了动态代理的基础概念,通过实例展示了如何实现和应用这两种方法,并比较了它们的性能差异及适用场景。进一步,探讨了在动态代理中实现熔断限流和日志监控的策略,以及如何利用动态代理优化Spring应用的设计和功能。
28 6
Spring高手之路17——动态代理的艺术与实践
|
14天前
|
XML Java 数据格式
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
19 0
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道