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

本文介绍了一个具体的Spring动态代理实现案例,包括自定义的抽象类ProxyFactoryBean及其子类ProviderProxyFactoryBean,展示了如何使用Spring AOP特性来创建动态代理对象,并提供了一种注册JDK动态代理类型Bean的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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,如需转载请自行联系原作者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值