Java tutorial
/* * Copyright 2009-2012 the original author or authors. * * 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 i 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.gzj.tulip.jade.context.spring; import com.gzj.tulip.jade.dataaccess.DataAccessFactory; import com.gzj.tulip.jade.dataaccess.DataAccessFactoryAdapter; import com.gzj.tulip.jade.dataaccess.DataSourceFactory; import com.gzj.tulip.jade.rowmapper.DefaultRowMapperFactory; import com.gzj.tulip.jade.rowmapper.RowMapperFactory; import com.gzj.tulip.jade.statement.Interpreter; import com.gzj.tulip.jade.statement.InterpreterFactory; import com.gzj.tulip.jade.statement.StatementWrapperProvider; import com.gzj.tulip.jade.statement.cached.CacheProvider; import com.gzj.tulip.load.ResourceRef; import com.gzj.tulip.load.RoseScanner; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationContextException; import org.springframework.context.annotation.ScannedGenericBeanDefinition; import org.springframework.core.annotation.Order; import org.springframework.core.io.Resource; import org.springframework.util.ResourceUtils; import javax.sql.DataSource; import java.io.File; import java.io.IOException; import java.util.*; /** * {@link JadeBeanFactoryPostProcessor} * ??applicationContext-jade.xmlSpring???? * ?Jade DAO ??SpringBeanSpring * <p/> * <p/> * <h1>==</h1> * <p/> * <p/> * jade?jar? applicationContext-jade.xml * ??Springjade???jade * ??????? * <p/> * <p/> * <strong>jade.context.spring</strong><br> * ?(?Jade??)jadespring??<br> * jade??DAO?Spring???? * ??jade * <p/> * <p/> * <strong>jade.context.spring.com.yourcompany.dao.UserDAO</strong><br> * ?0101?<br> * jadespring????0DAO??Spring? * 1DAO?Spring?<br> * jade?jade.context.spring.com.yourcompany.dao * jade.context.spring.*Jade * <p/> * <p/> * <strong>jade.context.spring.*</strong><br> * ? jade.context.spring.com jade.context.spring.cn * jade.context.spring.*, ? jade.context.spring<br> * jade 1?0 * ?1package????Spring * <p/> * <p/> * <h1>=DAO?=</h1> * <p/> * ? {@link RoseScanner#getJarOrClassesFolderResources()} * ?classes?rosejar? * jarDAO?rose?daoDAO * <p/> * ??classesjar?jadeDAO? * <ul> * <li> * DAO?package?daodao.UserDAO?myapp.dao.UserDAO?myapp.dao.blog * .BlogDAO</li> * <li>DAO?DAOUserDAO?BlogDAO</li> * <li>DAO?@DAOJade???Class.forName</li> * </ul> * <p/> * ??DAO????? {@link JadeFactoryBean} * ?Spring * <p/> * <h1>=??=</h1> * <p/> * ?? {@link DataSource} ????jade{@link DataSourceFactory} * ?DAO?????spring???? * <p/> * <h2>==?==</h2><br> * <ul> * <li>spring?id/name "jade.dataSourceFactory" * jadebean?? {@link DataSourceFactory}DAO????</li> * <li>springid/name "jade.dataSourceFactory"??? * {@link DataSourceFactory}jadebean ??DAO????</li> * <li>springid/name "jade.dataSourceFactory" * {@link DataSourceFactory}1??DAO? * IllegalStateException ?? {@link SpringDataSourceFactoryDelegate}</li> * </ul> * <p/> * <h2>==?==</h2><br> * spring? {@link DataSourceFactory} jade??DAO???? * {@link SpringDataSourceFactory} * DAO????spring??DAO? * com.mycompany.myapp.dao.UserDAO, * <p/> * <ul> * <li>id/namejade.dataSource.com.mycompany.myapp.dao. * UserDAO??DAO???????jade.dataSource.com</li> * <li>?UserDAO??UserDAO?<code>@DAO</code> * catalog??myteam.myappmyteam.myapp?package???</li> * <ul> * <li>??Spring?jade.dataSource.myteam.myapp.UserDAO...jade. * dataSource.myteam</li> * </ul> * <li> * ?UserDAO???id/namejade.dataSource?dataSource??</li> * <li> * ?UserDAO?????</li> * </ul> <br> * <p/> * <h1>=SQL?=</h1> * <p/> * DAO??jadeSQL??/SQL????<br> * Jade {@link InterpreterFactory} ?DAO?? ? * {@link InterpreterFactory} {@link SpringInterpreterFactory}<br> * {@link SpringInterpreterFactory}??Spring {@link Interpreter} * {@link Order}??DAO * * @author [qieqie.wang@gmail.com] * @author [in355hz@gmail.com] */ public class JadeBeanFactoryPostProcessor implements BeanFactoryPostProcessor { private static ResourceBundle bundle; static { try { bundle = ResourceBundle.getBundle("rose"); } catch (Exception e) { //e.printStackTrace(); } } /** * ?? */ private static final String propertyPrefix = "jade.context.spring"; /** * */ private final Log logger = LogFactory.getLog(JadeBeanFactoryPostProcessor.class); /** * ????? * <p/> * * @see #getDataAccessFactory(ConfigurableListableBeanFactory) */ private DataAccessFactory dataAccessFactory; /** * ????? * <p/> * * @see #getRowMapperFactory() */ private RowMapperFactory rowMapperFactory; /** * ?DAO????DAO?SQL??? * <p/> * * @see #getInterpreterFactory(ConfigurableListableBeanFactory) */ private InterpreterFactory interpreterFactory; /** * StatmentWrapper??bean??none?null */ private String statmentWrapperProviderName; /** * ??bean??none?null */ private String cacheProviderName; // ------------------------------ public DataAccessFactory getDataAccessFactory(ConfigurableListableBeanFactory beanFactory) { if (this.dataAccessFactory == null) { dataAccessFactory = new DataAccessFactoryAdapter(// new SpringDataSourceFactoryDelegate(beanFactory)); } return dataAccessFactory; } public InterpreterFactory getInterpreterFactory(ConfigurableListableBeanFactory beanFactory) { if (interpreterFactory == null) { interpreterFactory = new SpringInterpreterFactory(beanFactory); } return interpreterFactory; } public RowMapperFactory getRowMapperFactory() { if (rowMapperFactory == null) { rowMapperFactory = new DefaultRowMapperFactory(); } return rowMapperFactory; } public void setRowMapperFactory(RowMapperFactory rowMapperFactory) { this.rowMapperFactory = rowMapperFactory; } public String getCacheProviderName(ConfigurableListableBeanFactory beanFactory) { if (cacheProviderName == null) { String[] names = beanFactory.getBeanNamesForType(CacheProvider.class); if (names.length == 0) { cacheProviderName = "none"; } else if (names.length == 1) { cacheProviderName = names[0]; } else { String topPriority = "jade.cacheProvider"; if (ArrayUtils.contains(names, topPriority)) { cacheProviderName = topPriority; } else { throw new IllegalStateException( "required not more than 1 CacheProvider, but found " + names.length); } } } return "none".equals(cacheProviderName) ? null : cacheProviderName; } public String getStatementWrapperProvider(ConfigurableListableBeanFactory beanFactory) { if (statmentWrapperProviderName == null) { String[] names = beanFactory.getBeanNamesForType(StatementWrapperProvider.class); if (names.length == 0) { statmentWrapperProviderName = "none"; } else if (names.length == 1) { statmentWrapperProviderName = names[0]; } else { String topPriority = "jade.statmentWrapperProvider"; if (ArrayUtils.contains(names, topPriority)) { statmentWrapperProviderName = topPriority; } else { throw new IllegalStateException( "required not more than 1 StatmentWrapperProvider, but found " + names.length); } } } return "none".equals(statmentWrapperProviderName) ? null : statmentWrapperProviderName; } // ------------------------------ /** * Spring??? Jade DAO * ??SpringBeanSpring * <p/> * <p/> * ?? applicationContext-jade.xml rose? * ??????JavaDoc * <p/> * * @see BeanFactoryPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory) */ @Override public final void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { String springFlag = System.getProperty(propertyPrefix); if (bundle != null) { try { springFlag = bundle.getString(propertyPrefix); } catch (Exception e) { //e.printStackTrace(); } } // ?jade.context.spring jadespring?? if (springFlag != null && springFlag.length() > 0) { logger.info("found " + propertyPrefix + "=" + springFlag); return; } // doPostProcessBeanFactory(beanFactory); } private void doPostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // if (logger.isInfoEnabled()) { logger.info("[jade] starting ..."); } // 1??rose?(ResourceRef)?classes?/META-INF/rose.properties/META-INF/MENIFEST.MF?rosejar final List<ResourceRef> resources = findRoseResources(); // 2???(resources)rose=*?rose=DAO?rose=dao?URL? List<String> urls = findJadeResources(resources); // 3??URL?DAO?JadeFactoryBean?Spring findJadeDAODefinitions(beanFactory, urls); // ? if (logger.isInfoEnabled()) { logger.info("[jade] exits"); } } /* * ?rosejar */ private List<ResourceRef> findRoseResources() { final List<ResourceRef> resources; try { resources = RoseScanner.getInstance().getJarOrClassesFolderResources(); } catch (IOException e) { throw new ApplicationContextException("error on getJarResources/getClassesFolderResources", e); } return resources; } /* * ?dao?DAOurl */ private List<String> findJadeResources(final List<ResourceRef> resources) { List<String> urls = new LinkedList<String>(); for (ResourceRef ref : resources) { if (ref.hasModifier("dao") || ref.hasModifier("DAO")) { try { Resource resource = ref.getResource(); File resourceFile = resource.getFile(); if (resourceFile.isFile()) { urls.add("jar:file:" + resourceFile.toURI().getPath() + ResourceUtils.JAR_URL_SEPARATOR); } else if (resourceFile.isDirectory()) { urls.add(resourceFile.toURI().toString()); } } catch (IOException e) { throw new ApplicationContextException("error on resource.getFile", e); } } } if (logger.isInfoEnabled()) { logger.info("[jade] found " + urls.size() + " jade urls: " + urls); } return urls; } /* * jar?DAO?Spring */ private void findJadeDAODefinitions(ConfigurableListableBeanFactory beanFactory, List<String> urls) { JadeComponentProvider provider = new JadeComponentProvider(); Set<String> daoClassNames = new HashSet<String>(); for (String url : urls) { if (logger.isInfoEnabled()) { logger.info("[jade] call 'jade/find'"); } Set<BeanDefinition> dfs = provider.findCandidateComponents(url); if (logger.isInfoEnabled()) { logger.info("[jade] found " + dfs.size() + " beanDefinition from '" + url + "'"); } for (BeanDefinition beanDefinition : dfs) { String daoClassName = beanDefinition.getBeanClassName(); if (getDisableFlag(daoClassName)) { if (logger.isDebugEnabled()) { logger.debug("[jade] ignored disabled jade dao class: " + daoClassName + " [" + url + "]"); } continue; } if (daoClassNames.contains(daoClassName)) { if (logger.isDebugEnabled()) { logger.debug( "[jade] ignored replicated jade dao class: " + daoClassName + " [" + url + "]"); } continue; } daoClassNames.add(daoClassName); registerDAODefinition(beanFactory, beanDefinition); } } } /* * DAO?Spring */ private void registerDAODefinition(ConfigurableListableBeanFactory beanFactory, BeanDefinition beanDefinition) { final String daoClassName = beanDefinition.getBeanClassName(); MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); /* * ?? JadeFactoryBean ?? */ propertyValues.addPropertyValue("objectType", daoClassName); propertyValues.addPropertyValue("dataAccessFactory", getDataAccessFactory(beanFactory)); propertyValues.addPropertyValue("rowMapperFactory", getRowMapperFactory()); propertyValues.addPropertyValue("interpreterFactory", getInterpreterFactory(beanFactory)); String cacheProviderName = getCacheProviderName(beanFactory); if (cacheProviderName != null) { RuntimeBeanReference beanRef = new RuntimeBeanReference(cacheProviderName); propertyValues.addPropertyValue("cacheProvider", beanRef); } String statementWrapperProvider = getStatementWrapperProvider(beanFactory); if (statementWrapperProvider != null) { RuntimeBeanReference beanRef = new RuntimeBeanReference(statementWrapperProvider); propertyValues.addPropertyValue("statementWrapperProvider", beanRef); } ScannedGenericBeanDefinition scannedBeanDefinition = (ScannedGenericBeanDefinition) beanDefinition; scannedBeanDefinition.setPropertyValues(propertyValues); scannedBeanDefinition.setBeanClass(JadeFactoryBean.class); DefaultListableBeanFactory defaultBeanFactory = (DefaultListableBeanFactory) beanFactory; defaultBeanFactory.registerBeanDefinition(daoClassName, beanDefinition); if (logger.isDebugEnabled()) { logger.debug("[jade] register DAO: " + daoClassName); } } /* * ?dao */ protected boolean getDisableFlag(String daoType) { String name = daoType; while (true) { String flag; if (name.length() == 0) { flag = System.getProperty(propertyPrefix + ".*"); if (bundle != null) { try { flag = bundle.getString(propertyPrefix + ".*"); } catch (Exception e) { //e.printStackTrace(); } } } else { flag = System.getProperty(propertyPrefix + "." + name); if (bundle != null) { try { flag = bundle.getString(propertyPrefix + "." + name); } catch (Exception e) { //e.printStackTrace(); } } } if (flag == null) { int index = name.lastIndexOf('.'); if (index == -1) { if (name.length() == 0) { return false; } else { name = ""; } } else { name = name.substring(0, index); } continue; } if ("0".equals(flag)) { return true; } else if (flag == null || "1".equals(flag)) { return false; } else { if (name.length() == 0) { name = "*"; } throw new IllegalArgumentException( "illegal value of property: " + propertyPrefix + "." + name + "='" + flag + "'"); } } } }