spring AbstractBeanDefinition创建bean类型是动态代理类的方式
1.接口 Class<?> resourceClass
2.获取builder
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(resourceClass);
3.获取接口对应的动态代理class
Class<?> targetProxyClass = Proxy.getProxyClass(XXX.class.getClassLoader(), new Class[]{resourceClass});
4.targetProxyClass构造参数类型 InvocationHandler,通过builder设置
builder.addConstructorArgValue(Proxy.getInvocationHandler(xxxProxyBean) 或者 new InvocationHandler(){...});
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.setBeanClass(targetProxyClass);
registry.registerBeanDefinition("beanName", beanDefinition);
5.记录一下自己曾经写的一个例子
5.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; } }
5.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}); } }
5.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; } }
5.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); } }
5.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; } }
5.6 附加SelfDubboAnnotationBean
package com.hjzgg.apigateway.dubbo.configure; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.common.utils.ConcurrentHashSet; import com.alibaba.dubbo.config.*; import com.alibaba.dubbo.config.annotation.Service; import com.alibaba.dubbo.config.spring.ReferenceBean; import com.alibaba.dubbo.config.spring.ServiceBean; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.ClassUtils; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @see com.alibaba.dubbo.config.spring.AnnotationBean */ public class SelfDubboAnnotationBean extends AbstractConfig implements DisposableBean, BeanPostProcessor, ApplicationContextAware, Serializable { private static final Logger logger = LoggerFactory.getLogger(Logger.class); private String annotationPackage; private String[] annotationPackages; private final Set<ServiceConfig<?>> serviceConfigs = new ConcurrentHashSet<>(); private final ConcurrentMap<String, ReferenceBean<?>> referenceConfigs = new ConcurrentHashMap<>(); public String getPackage() { return annotationPackage; } public void setPackage(String annotationPackage) { this.annotationPackage = annotationPackage; this.annotationPackages = (annotationPackage == null || annotationPackage.length() == 0) ? null : Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); } private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void destroy() throws Exception { for (ServiceConfig<?> serviceConfig : serviceConfigs) { try { serviceConfig.unexport(); } catch (Throwable e) { logger.error(e.getMessage(), e); } } for (ReferenceConfig<?> referenceConfig : referenceConfigs.values()) { try { referenceConfig.destroy(); } catch (Throwable e) { logger.error(e.getMessage(), e); } } } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (! isMatchPackage(bean)) { return bean; } if (AopUtils.isAopProxy(bean)) { /** * @see com.hjzgg.apigateway.soa.executor.RegisterBeanUtils#registerProvider * @see com.hjzgg.apigateway.soa.proxy.provider.ProviderDynamicProxy#invoke * */ //获取被代理的真实类或者接口类 Class<?> targetClass = AopUtils.getTargetClass(bean); Service service = targetClass.getAnnotation(Service.class); if (service != null) { ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service); if (void.class.equals(service.interfaceClass()) && "".equals(service.interfaceName())) { if (!(targetClass.isInterface() || targetClass.getInterfaces().length > 0)) { throw new IllegalStateException("Failed to export remote service class " + bean.getClass().getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces."); } else { if (targetClass.isInterface()) { serviceConfig.setInterface(targetClass); } if (targetClass.getInterfaces().length > 0) { serviceConfig.setInterface(targetClass.getInterfaces()[0]); } } } if (applicationContext != null) { serviceConfig.setApplicationContext(applicationContext); if (service.registry() != null && service.registry().length > 0) { List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); for (String registryId : service.registry()) { if (registryId != null && registryId.length() > 0) { registryConfigs.add(applicationContext.getBean(registryId, RegistryConfig.class)); } } serviceConfig.setRegistries(registryConfigs); } if (service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider(applicationContext.getBean(service.provider(),ProviderConfig.class)); } if (service.monitor() != null && service.monitor().length() > 0) { serviceConfig.setMonitor(applicationContext.getBean(service.monitor(), MonitorConfig.class)); } if (service.application() != null && service.application().length() > 0) { serviceConfig.setApplication(applicationContext.getBean(service.application(), ApplicationConfig.class)); } if (service.module() != null && service.module().length() > 0) { serviceConfig.setModule(applicationContext.getBean(service.module(), ModuleConfig.class)); } if (service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider(applicationContext.getBean(service.provider(), ProviderConfig.class)); } if (service.protocol() != null && service.protocol().length > 0) { List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>(); for (String protocolId : service.registry()) { if (protocolId != null && protocolId.length() > 0) { protocolConfigs.add(applicationContext.getBean(protocolId, ProtocolConfig.class)); } } serviceConfig.setProtocols(protocolConfigs); } try { serviceConfig.afterPropertiesSet(); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } serviceConfig.setRef(bean); serviceConfigs.add(serviceConfig); serviceConfig.export(); } } return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Service service = (AopUtils.isAopProxy(bean) && !Objects.isNull(AopUtils.getTargetClass(bean).getAnnotation(Service.class))) ? AopUtils.getTargetClass(bean).getAnnotation(Service.class) : bean.getClass().getAnnotation(Service.class); if (Objects.isNull(service)) { return bean; } try { InvocationHandler h = Proxy.getInvocationHandler(service); // 获取 AnnotationInvocationHandler 的 memberValues 字段 Field memberValuesField = h.getClass().getDeclaredField("memberValues"); // 因为这个字段事 private final 修饰,所以要打开权限 memberValuesField.setAccessible(true); // 获取 memberValues Map memberValues = (Map) memberValuesField.get(h); Service serviceInstance = Stream.of(bean.getClass().getInterfaces()) .filter(iface -> iface.getAnnotation(Service.class) != null) .collect(Collectors.toList()) .get(0) .getAnnotation(Service.class); memberValues.put("version", serviceInstance.version()); memberValues.put("group", serviceInstance.group()); } catch (Exception e) { throw new BeanCreationException(String.format("%s %s %s %s %s" , "修改" , ClassUtils.getQualifiedName(bean.getClass()) , "的注解" , ClassUtils.getQualifiedName(Service.class) , "的 group值和version值出错") , e); } return bean; } private boolean isMatchPackage(Object bean) { if (annotationPackages == null || annotationPackages.length == 0) { return true; } String beanClassName = bean.getClass().getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; } } return false; } }
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; }
本文来自博客园,作者:hjzqyx,转载请注明原文链接:https://www.cnblogs.com/hujunzheng/p/8527338.html