基于javaConfig的springDataJpa+dubbo+springMvc搭建(二)
2015-12-31 01:15
721 查看
前文基本把dubbo框架搭出来了,本文在此框架,重点解决@org.springframework.transaction.annotation.Transactional带出的问题,以加入简单的权限管理功能进来为例.当然要完善这个框架之前,会先把权限的开关关闭.即注释org.exam.web.config.MvcConfig#addInterceptors方法.使用了spring data jpa,解决懒加载,可以离不开Transactional注解.不知算不算bug,到了现在的dubbox也没更改,总之就出了问题.先看看问题:一个服务实现类加了@Transactional,使用注解扫描就不能暴露服务(网上有解决办法,试了,没有效果).
具体出现问题例子:用户与角色是多对多的关系,查询列表时,没必要加载用户的角色,但查询某个用户时,可将用户的角色查询出来.
用户与角色的实体关系:
查询用户分页数据:
查询某个用户数据:
使用扫描方法暴露Dubbo服务的主要逻辑在
因为使用了@Transactional注解,spring就会生成代理实例注册成Bean,所我所知,以上几个地方都不够严谨科学,对于新版本的spring已不能适应.因此将整个类修改如下:
来源:https://raw.githubusercontent.com/dangdangdotcom/dubbox/master/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java
本文源码:http://download.csdn.net/detail/xiejx618/9384819
具体出现问题例子:用户与角色是多对多的关系,查询列表时,没必要加载用户的角色,但查询某个用户时,可将用户的角色查询出来.
用户与角色的实体关系:
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinTable(name = Constants.TABLE_PREFIX + "user_role") private Set<Role> roles = new HashSet<Role>();
查询用户分页数据:
public Page<User> findAll(String id, String username, Pageable pageable) { return userRepository.findAll((root, query, cb) -> { List<Predicate> criteria = new ArrayList<>(); if (StringUtils.hasLength(id)) { criteria.add(cb.equal(root.get(User_.id), id)); } if (StringUtils.hasLength(username)) { criteria.add(cb.like(root.get(User_.username), "%" + username + "%")); } if (criteria.size() > 0) { return cb.and(criteria.toArray(new Predicate[criteria.size()])); } else { return null; } }, pageable); }
查询某个用户数据:
@Transactional(readOnly = true)//解决懒加载 public User findOne(String id) { User user = userRepository.findOne(id); user.getRoles().forEach(Role::getId); return user; }
使用扫描方法暴露Dubbo服务的主要逻辑在
com.alibaba.dubbo.config.spring.AnnotationBean public class AnnotationBean extends AbstractConfig implements DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, ApplicationContextAware { //其它省略 //主要将带有com.alibaba.dubbo.config.annotation.Service注解的类注册成Bean public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (annotationPackage == null || annotationPackage.length() == 0) { return; } if (beanFactory instanceof BeanDefinitionRegistry) { try { // init scanner Class<?> scannerClass = ReflectUtils.forName("org.springframework.context.annotation.ClassPathBeanDefinitionScanner"); Object scanner = scannerClass.getConstructor(new Class<?>[] {BeanDefinitionRegistry.class, boolean.class}).newInstance(new Object[] {(BeanDefinitionRegistry) beanFactory, true}); // add filter Class<?> filterClass = ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter"); Object filter = filterClass.getConstructor(Class.class).newInstance(Service.class); Method addIncludeFilter = scannerClass.getMethod("addIncludeFilter", ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter")); addIncludeFilter.invoke(scanner, filter); // scan packages String[] packages = Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); Method scan = scannerClass.getMethod("scan", new Class<?>[]{String[].class}); scan.invoke(scanner, new Object[] {packages}); } catch (Throwable e) { // spring 2.0 } } } //主要将带有com.alibaba.dubbo.config.annotation.Service注解的类的方法暴露成服务. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { //看以下注释 if (! isMatchPackage(bean)) { return bean; } //如果经过了代理,这里也获取不到 Service service = bean.getClass().getAnnotation(Service.class); if (service != null) { ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service); if (void.class.equals(service.interfaceClass()) && "".equals(service.interfaceName())) { if (bean.getClass().getInterfaces().length > 0) { //经过了代理,这里也不对 serviceConfig.setInterface(bean.getClass().getInterfaces()[0]); } else { 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."); } } 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((RegistryConfig)applicationContext.getBean(registryId, RegistryConfig.class)); } } serviceConfig.setRegistries(registryConfigs); } if (service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider((ProviderConfig)applicationContext.getBean(service.provider(),ProviderConfig.class)); } if (service.monitor() != null && service.monitor().length() > 0) { serviceConfig.setMonitor((MonitorConfig)applicationContext.getBean(service.monitor(), MonitorConfig.class)); } if (service.application() != null && service.application().length() > 0) { serviceConfig.setApplication((ApplicationConfig)applicationContext.getBean(service.application(), ApplicationConfig.class)); } if (service.module() != null && service.module().length() > 0) { serviceConfig.setModule((ModuleConfig)applicationContext.getBean(service.module(), ModuleConfig.class)); } if (service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider((ProviderConfig)applicationContext.getBean(service.provider(), ProviderConfig.class)); } else { } 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((ProtocolConfig)applicationContext.getBean(protocolId, ProtocolConfig.class)); } } serviceConfig.setProtocols(protocolConfigs); } try { serviceConfig.afterPropertiesSet(); } catch (RuntimeException e) { throw (RuntimeException) e; } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } serviceConfig.setRef(bean); serviceConfigs.add(serviceConfig); serviceConfig.export(); } return bean; } private boolean isMatchPackage(Object bean) { if (annotationPackages == null || annotationPackages.length == 0) { return true; } //如果是JDK代理过的类,这里判断就会有错 String beanClassName = bean.getClass().getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; } } return false; } }
因为使用了@Transactional注解,spring就会生成代理实例注册成Bean,所我所知,以上几个地方都不够严谨科学,对于新版本的spring已不能适应.因此将整个类修改如下:
来源:https://raw.githubusercontent.com/dangdangdotcom/dubbox/master/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java
/* * Copyright 1999-2012 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.dubbo.config.spring; 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.common.utils.ReflectUtils; import com.alibaba.dubbo.config.*; import com.alibaba.dubbo.config.annotation.Reference; import com.alibaba.dubbo.config.annotation.Service; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * AnnotationBean * * @author william.liangf * @export */ public class AnnotationBean extends AbstractConfig implements DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, ApplicationContextAware { private static final long serialVersionUID = -7582802454287589552L; private static final Logger logger = LoggerFactory.getLogger(Logger.class); private String annotationPackage; private String[] annotationPackages; private final Set<ServiceConfig<?>> serviceConfigs = new ConcurrentHashSet<ServiceConfig<?>>(); private final ConcurrentMap<String, ReferenceBean<?>> referenceConfigs = new ConcurrentHashMap<String, ReferenceBean<?>>(); 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 postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (annotationPackage == null || annotationPackage.length() == 0) { return; } if (beanFactory instanceof BeanDefinitionRegistry) { try { // init scanner Class<?> scannerClass = ReflectUtils.forName("org.springframework.context.annotation.ClassPathBeanDefinitionScanner"); Object scanner = scannerClass.getConstructor(new Class<?>[]{BeanDefinitionRegistry.class, boolean.class}).newInstance(new Object[]{(BeanDefinitionRegistry) beanFactory, true}); // add filter Class<?> filterClass = ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter"); Object filter = filterClass.getConstructor(Class.class).newInstance(Service.class); Method addIncludeFilter = scannerClass.getMethod("addIncludeFilter", ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter")); addIncludeFilter.invoke(scanner, filter); // scan packages String[] packages = Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); Method scan = scannerClass.getMethod("scan", new Class<?>[]{String[].class}); scan.invoke(scanner, new Object[]{packages}); } catch (Throwable e) { // spring 2.0 } } } 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; } Class<?> clazz = bean.getClass(); if (isProxyBean(bean)) { clazz = AopUtils.getTargetClass(bean); } Service service = clazz.getAnnotation(Service.class); if (service != null) { ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service); if (void.class.equals(service.interfaceClass()) && "".equals(service.interfaceName())) { if (clazz.getInterfaces().length > 0) { serviceConfig.setInterface(clazz.getInterfaces()[0]); } else { throw new IllegalStateException("Failed to export remote service class " + clazz.getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces."); } } 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((RegistryConfig) applicationContext.getBean(registryId, RegistryConfig.class)); } } serviceConfig.setRegistries(registryConfigs); } if (service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider((ProviderConfig) applicationContext.getBean(service.provider(), ProviderConfig.class)); } if (service.monitor() != null && service.monitor().length() > 0) { serviceConfig.setMonitor((MonitorConfig) applicationContext.getBean(service.monitor(), MonitorConfig.class)); } if (service.application() != null && service.application().length() > 0) { serviceConfig.setApplication((ApplicationConfig) applicationContext.getBean(service.application(), ApplicationConfig.class)); } if (service.module() != null && service.module().length() > 0) { serviceConfig.setModule((ModuleConfig) applicationContext.getBean(service.module(), ModuleConfig.class)); } if (service.provider() != null && service.provider().length() > 0) { serviceConfig.setProvider((ProviderConfig) applicationContext.getBean(service.provider(), ProviderConfig.class)); } else { } if (service.protocol() != null && service.protocol().length > 0) { List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>(); // modified by lishen; fix dubbo's bug for (String protocolId : service.protocol()) { if (protocolId != null && protocolId.length() > 0) { protocolConfigs.add((ProtocolConfig) applicationContext.getBean(protocolId, ProtocolConfig.class)); } } serviceConfig.setProtocols(protocolConfigs); } try { serviceConfig.afterPropertiesSet(); } catch (RuntimeException e) { throw (RuntimeException) 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 { if (!isMatchPackage(bean)) { return bean; } Class<?> clazz = bean.getClass(); if (isProxyBean(bean)) { clazz = AopUtils.getTargetClass(bean); } Method[] methods = clazz.getMethods(); for (Method method : methods) { String name = method.getName(); if (name.length() > 3 && name.startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers()) && !Modifier.isStatic(method.getModifiers())) { try { Reference reference = method.getAnnotation(Reference.class); if (reference != null) { Object value = refer(reference, method.getParameterTypes()[0]); if (value != null) { method.invoke(bean, new Object[]{value}); } } } catch (Exception e) { // modified by lishen throw new BeanInitializationException("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName(), e); // logger.error("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); } } } Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { try { if (!field.isAccessible()) { field.setAccessible(true); } Reference reference = field.getAnnotation(Reference.class); if (reference != null) { Object value = refer(reference, field.getType()); if (value != null) { field.set(bean, value); } } } catch (Exception e) { // modified by lishen throw new BeanInitializationException("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName(), e); // logger.error("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); } } return bean; } private Object refer(Reference reference, Class<?> referenceClass) { //method.getParameterTypes()[0] String interfaceName; if (!"".equals(reference.interfaceName())) { interfaceName = reference.interfaceName(); } else if (!void.class.equals(reference.interfaceClass())) { interfaceName = reference.interfaceClass().getName(); } else if (referenceClass.isInterface()) { interfaceName = referenceClass.getName(); } else { throw new IllegalStateException("The @Reference undefined interfaceClass or interfaceName, and the property type " + referenceClass.getName() + " is not a interface."); } String key = reference.group() + "/" + interfaceName + ":" + reference.version(); ReferenceBean<?> referenceConfig = referenceConfigs.get(key); if (referenceConfig == null) { referenceConfig = new ReferenceBean<Object>(reference); if (void.class.equals(reference.interfaceClass()) && "".equals(reference.interfaceName()) && referenceClass.isInterface()) { referenceConfig.setInterface(referenceClass); } if (applicationContext != null) { referenceConfig.setApplicationContext(applicationContext); if (reference.registry() != null && reference.registry().length > 0) { List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); for (String registryId : reference.registry()) { if (registryId != null && registryId.length() > 0) { registryConfigs.add((RegistryConfig) applicationContext.getBean(registryId, RegistryConfig.class)); } } referenceConfig.setRegistries(registryConfigs); } if (reference.consumer() != null && reference.consumer().length() > 0) { referenceConfig.setConsumer((ConsumerConfig) applicationContext.getBean(reference.consumer(), ConsumerConfig.class)); } if (reference.monitor() != null && reference.monitor().length() > 0) { referenceConfig.setMonitor((MonitorConfig) applicationContext.getBean(reference.monitor(), MonitorConfig.class)); } if (reference.application() != null && reference.application().length() > 0) { referenceConfig.setApplication((ApplicationConfig) applicationContext.getBean(reference.application(), ApplicationConfig.class)); } if (reference.module() != null && reference.module().length() > 0) { referenceConfig.setModule((ModuleConfig) applicationContext.getBean(reference.module(), ModuleConfig.class)); } if (reference.consumer() != null && reference.consumer().length() > 0) { referenceConfig.setConsumer((ConsumerConfig) applicationContext.getBean(reference.consumer(), ConsumerConfig.class)); } try { referenceConfig.afterPropertiesSet(); } catch (RuntimeException e) { throw (RuntimeException) e; } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } referenceConfigs.putIfAbsent(key, referenceConfig); referenceConfig = referenceConfigs.get(key); } return referenceConfig.get(); } private boolean isMatchPackage(Object bean) { if (annotationPackages == null || annotationPackages.length == 0) { return true; } Class clazz = bean.getClass(); if (isProxyBean(bean)) { clazz = AopUtils.getTargetClass(bean); } String beanClassName = clazz.getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; } } return false; } private boolean isProxyBean(Object bean) { return AopUtils.isAopProxy(bean); } }
本文源码:http://download.csdn.net/detail/xiejx618/9384819
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- 模拟Spring的简单实现
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao
- 读取spring配置文件的方法(spring读取资源文件)
- Spring Bean基本管理实例详解
- java实现简单美女拼图游戏
- 详解Java的Spring框架中的事务管理方式
- 解析Java的Spring框架的BeanPostProcessor发布处理器
- Java开发框架spring实现自定义缓存标签
- java基本教程之线程休眠 java多线程教程
- JSP开发中在spring mvc项目中实现登录账号单浏览器登录
- spring boot实战之内嵌容器tomcat配置
- 浅析Java的Spring框架中IOC容器容器的应用
- 基于Spring框架的Shiro配置方法