java 扩展接口_详解常用的Spring Bean扩展接口

前言

Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心。

Spring框架运用了非常多的设计模式,从整体上看,它的设计严格遵循了OCP----开闭原则,即:

1、保证对修改关闭,即外部无法修改Spring整个运作的流程

2、提供对扩展开放,即可以通过继承、实现Spring提供的众多抽象类与接口来改变类加载的行为

开卷有益,阅读Spring源码(无需每个类都看得很细,大体流程能梳理出来即可)对于个人水平的提升是帮助非常大的,同时也能在工作中即使发现和解决一些不常见的Spring问题。

不过,本文的目的不是整理Spring的流程,而是通过介绍一些常用的Spring Bean工具类,来让我们可以更好地使用Spring提供给开发者的多种特性,下面让我们开始吧。

InitialingBean和DisposableBean

InitialingBean是一个接口,提供了一个唯一的方法afterPropertiesSet()。

DisposableBean也是一个接口,提供了一个唯一的方法destory()。

这两个接口是一组的,功能类似,因此放在一起:前者顾名思义在Bean属性都设置完毕后调用afterPropertiesSet()方法做一些初始化的工作,后者在Bean生命周期结束前调用destory()方法做一些收尾工作。下面看一下例子,为了能明确地知道afterPropertiesSet()方法的调用时机,加上一个属性,给属性set方法,在set方法中打印一些内容:

/**

* @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html

*/

public class LifecycleBean implements InitializingBean, DisposableBean

{

@SuppressWarnings("unused")

private String lifeCycleBeanName;

public void setLifeCycleBeanName(String lifeCycleBeanName)

{

System.out.println("Enter LifecycleBean.setLifeCycleBeanName(), lifeCycleBeanName = " + lifeCycleBeanName);

this.lifeCycleBeanName = lifeCycleBeanName;

}

public void destroy() throws Exception

{

System.out.println("Enter LifecycleBean.destroy()");

}

public void afterPropertiesSet() throws Exception

{

System.out.println("Enter LifecycleBean.afterPropertiesSet()");

}

public void beanStart()

{

System.out.println("Enter LifecycleBean.beanStart()");

}

public void beanEnd()

{

System.out.println("Enter LifecycleBean.beanEnd()");

}

}

配置一个spring.xml:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

启动Spring容器,LifecycleBean执行的结果为:

Enter LifecycleBean.setLifeCycleBeanName(), lifeCycleBeanName = lifeCycleBean

Enter LifecycleBean.afterPropertiesSet()

Enter LifecycleBean.beanStart()

Enter LifecycleBean.destroy()

Enter LifecycleBean.beanEnd()

执行结果和我们想的一样,afterPropertiesSet()方法就如同它的名字所表示的那样,是在Bean的属性都被设置完毕之后,才会调用。

关于这两个接口,我总结几点:

1、InitializingBean接口、Disposable接口可以和init-method、destory-method配合使用,接口执行顺序优先于配置

2、InitializingBean接口、Disposable接口底层使用类型强转.方法名()进行直接方法调用,init-method、destory-method底层使用反射,前者和Spring耦合程度更高但效率高,后者解除了和Spring之间的耦合但是效率低,使用哪个看个人喜好

3、afterPropertiesSet()方法是在Bean的属性设置之后才会进行调用,某个Bean的afterPropertiesSet()方法执行完毕才会执行下一个Bean的afterPropertiesSet()方法,因此不建议在afterPropertiesSet()方法中写处理时间太长的方法

BeanNameAware、ApplicationContextAware和BeanFactoryAware

这三个接口放在一起写,是因为它们是一组的,作用相似。

"Aware"的意思是"感知到的",那么这三个接口的意思也不难理解:

1、实现BeanNameAware接口的Bean,在Bean加载的过程中可以获取到该Bean的id

2、实现ApplicationContextAware接口的Bean,在Bean加载的过程中可以获取到Spring的ApplicationContext,这个尤其重要,ApplicationContext是Spring应用上下文,从ApplicationContext中可以获取包括任意的Bean在内的大量Spring容器内容和信息

3、实现BeanFactoryAware接口的Bean,在Bean加载的过程中可以获取到加载该Bean的BeanFactory

看一下例子:

/**

* @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html

*/

public class AwareBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware

{

private String beanName;

private ApplicationContext applicationContext;

private BeanFactory beanFactory;

public void setBeanName(String beanName)

{

System.out.println("Enter AwareBean.setBeanName(), beanName = " + beanName + "\n");

this.beanName = beanName;

}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException

{

System.out.println("Enter AwareBean.setApplicationContext(), applicationContext = " + applicationContext + "\n");

this.applicationContext = applicationContext;

}

public void setBeanFactory(BeanFactory beanFactory) throws BeansException

{

System.out.println("Enter AwareBean.setBeanFactory(), beanfactory = " + beanFactory + "\n");

this.beanFactory = beanFactory;

}

}

配置一个Spring.xml:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

启动Spring容器后的执行结果为:

Enter AwareBean.setBeanName(), beanName = AwareBean

Enter AwareBean.setBeanFactory(), beanfactory = org.springframework.beans.factory.support.DefaultListableBeanFactory@2747fda0: defining beans [AwareBean,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor]; root of factory hierarchy

Enter AwareBean.setApplicationContext(), applicationContext = org.springframework.context.support.GenericApplicationContext@5514cd80: startup date [Mon Aug 08 19:23:30 CST 2016]; root of context hierarchy

关于这三个接口以及上面的打印信息,总结几点:

1、如果你的BeanName、ApplicationContext、BeanFactory有用,那么就自己定义一个变量将它们保存下来,如果没用,那么只需要实现setXXX()方法,用一下Spring注入进来的参数即可

2、如果Bean同时还实现了InitializingBean,容器会保证BeanName、ApplicationContext和BeanFactory在调用afterPropertiesSet()方法被注入

FactoryBean

FactoryBean在Spring中是非常有用的,使用Eclipse/MyEclipse的朋友可以对FactoryBean使用ctrl+t查看一下,FactoryBean这个接口在Spring容器中有大量的子实现。

传统的Spring容器加载一个Bean的整个过程,都是由Spring控制的,换句话说,开发者除了设置Bean相关属性之外,是没有太多的自主权的。FactoryBean改变了这一点,开发者可以个性化地定制自己想要实例化出来的Bean,方法就是实现FactoryBean接口。

看一下代码例子,为了讲清楚FactoryBean,内容相对多一些,首先定义一个接口Animal:

public interface Animal

{

public void move();

}

定义两个实现类Monkey和Tiger:

public class Monkey implements Animal

{

public void move()

{

System.out.println("Monkey move!");

}

}

public class Tiger implements Animal

{

public void move()

{

System.out.println("Tiger move!");

}

}

写一个实现类,实现FactoryBean接口:

/**

* @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html

*/

public class AnimalFactoryBean implements FactoryBean

{

private String animal;

public Animal getObject() throws Exception

{

if ("Monkey".equals(animal))

{

return new Monkey();

}

else if ("Tiger".equals(animal))

{

return new Tiger();

}

else

{

return null;

}

}

public Class> getObjectType()

{

return Animal.class;

}

public boolean isSingleton()

{

return true;

}

public void setAnimal(String animal)

{

this.animal = animal;

}

}

配置一个spring.xml,注入属性Tiger:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

写一个JUnit的测试类:

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {

"classpath*:spring.xml",

})

public class BaseTest

{

@Resource

private Animal animal;

@Test

public void aa()

{

animal.move();

}

}

查看一下运行结果:

Tiger move!

看到最后得到的并不是FactoryBean本身,而是FactoryBean的泛型对象,这就是FactoryBean的作用。FactoryBean的几个方法:

1、getObject()方法是最重要的,控制Bean的实例化过程

2、getObjectType()方法获取接口返回的实例的class

3、isSingleton()方法获取该Bean是否为一个单例的Bean

像我这段代码的功能就是传入一个String类型的参数,可以动态控制生成出来的是接口的哪种子类。有了FactoryBean,同样的我们也可以灵活地操控Bean的生成。

BeanPostProcessor

之前的InitializingBean、DisposableBean、FactoryBean包括init-method和destory-method,针对的都是某个Bean控制其初始化的操作,而似乎没有一种办法可以针对每个Bean的生成前后做一些逻辑操作,PostProcessor则帮助我们做到了这一点,先看一个简单的BeanPostProcessor。

网上有一张图画了Bean生命周期的过程,画得挺好,原图出处:

92233c031a57322e0f76edaec534948b.png

BeanPostProcess接口有两个方法,都可以见名知意:

1、postProcessBeforeInitialization:在初始化Bean之前

2、postProcessAfterInitialization:在初始化Bean之后

值得注意的是,这两个方法是有返回值的,不要返回null,否则getBean的时候拿不到对象。

写一段测试代码,首先定义一个普通的Bean,为了后面能区分,给Bean加一个属性:

public class CommonBean

{

private String commonName;

public void setCommonName(String commonName)

{

this.commonName = commonName;

}

public void initMethod()

{

System.out.println("Enter CommonBean.initMethod(), commonName = " + commonName);

}

}

定义一个PostProcess,实现BeanPostProcess接口:

/**

* @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html

*/

public class PostProcessorBean implements BeanPostProcessor

{

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException

{

System.out.println("Enter ProcessorBean.postProcessAfterInitialization()\n");

return bean;

}

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException

{

System.out.println("Enter ProcessorBean.postProcessBeforeInitialization()");

return bean;

}

}

配置一个spring.xml,给CommonBean的commonName赋予不同的值以区分:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

运行一个Spring容器, 初始化结果为:

Enter ProcessorBean.postProcessBeforeInitialization()

Enter CommonBean.initMethod(), commonName = common0

Enter ProcessorBean.postProcessAfterInitialization()

Enter ProcessorBean.postProcessBeforeInitialization()

Enter CommonBean.initMethod(), commonName = common1

Enter ProcessorBean.postProcessAfterInitialization()

Enter ProcessorBean.postProcessBeforeInitialization()

Enter ProcessorBean.postProcessAfterInitialization()

看到每个Bean初始化前后都会分别执行postProcessorBeforeInitiallization()方法与postProcessorAfterInitialization()方法,最后两行出现原因是,PostProcessorBean本身也是一个Bean。

BeanFactoryPostProcessor

接下来看另外一个PostProcessor----BeanFactoryPostProcessor。

Spring允许在Bean创建之前,读取Bean的元属性,并根据自己的需求对元属性进行改变,比如将Bean的scope从singleton改变为prototype,最典型的应用应当是PropertyPlaceholderConfigurer,替换xml文件中的占位符,替换为properties文件中相应的key对应的value,这将会在下篇文章中专门讲解PropertyPlaceholderConfigurer的作用及其原理。

BeanFactoryPostProcessor就可以帮助我们实现上述的功能,下面来看一下BeanFactoryPostProcessor的使用,定义一个BeanFactoryPostProcessor的实现类:

/**

* @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html

*/

public class FactoryPostProcessorBean implements BeanFactoryPostProcessor

{

public void postProcessBeanFactory(ConfigurableListableBeanFactory configurablelistablebeanfactory)

throws BeansException

{

System.out.println("Enter FactoryPostProcessorBean.postProcessBeanFactory()\n");

}

}

spring.xml里面配置一下这个Bean,就不写了,运行一下Spring容器,结果为:

Enter FactoryPostProcessorBean.postProcessBeanFactory()

Enter ProcessorBean.postProcessBeforeInitialization()

Enter CommonBean.initMethod(), commonName = common0

Enter ProcessorBean.postProcessAfterInitialization()

Enter ProcessorBean.postProcessBeforeInitialization()

Enter CommonBean.initMethod(), commonName = common1

Enter ProcessorBean.postProcessAfterInitialization()

Enter ProcessorBean.postProcessBeforeInitialization()

Enter ProcessorBean.postProcessAfterInitialization()

从执行结果中可以看出两点:

1、BeanFactoryPostProcessor的执行优先级高于BeanPostProcessor

2、BeanFactoryPostProcessor的postProcessBeanFactory()方法只会执行一次

注意到postProcessBeanFactory方法是带了参数ConfigurableListableBeanFactory的,这就和我之前说的可以使用BeanFactoryPostProcessor来改变Bean的属性相对应起来了。ConfigurableListableBeanFactory功能非常丰富,最基本的,它携带了每个Bean的基本信息,比如我简单写一段代码:

/**

* @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html

*/

public void postProcessBeanFactory(ConfigurableListableBeanFactory configurablelistablebeanfactory)

throws BeansException

{

BeanDefinition beanDefinition = configurablelistablebeanfactory.getBeanDefinition("common0");

MutablePropertyValues beanProperty = beanDefinition.getPropertyValues();

System.out.println("scope before change:" + beanDefinition.getScope());

beanDefinition.setScope("singleton");

System.out.println("scope after change:" + beanDefinition.getScope());

System.out.println("beanProperty:" + beanProperty);

}

看一下执行结果:

scope before change:

scope after change:singleton

beanProperty:PropertyValues: length=1; bean property 'commonName'

这样就获取了Bean的生命周期以及重新设置了Bean的生命周期。ConfigurableListableBeanFactory还有很多的功能,比如添加BeanPostProcessor,可以自己去查看。

InstantiationAwareBeanPostProcessor

最后写一个叫做InstantiationAwareBeanPostProcessor的PostProcessor。

InstantiationAwareBeanPostProcessor又代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:

1、实例化----实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中

2、初始化----初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

之前的BeanPostProcessor作用于过程(2)前后,现在的InstantiationAwareBeanPostProcessor则作用于过程(1)前后,看一下代码,给前面的CommonBean加上构造函数:

public class CommonBean

{

public CommonBean()

{

System.out.println("Enter CommonBean's constructor");

}

private String commonName;

public void setCommonName(String commonName)

{

System.out.println("Enter CommonBean.setCommonName(), commonName = " + commonName);

this.commonName = commonName;

}

public void initMethod()

{

System.out.println("Enter CommonBean.initMethod(), commonName = " + commonName);

}

}

实现InstantiationAwareBeanPostProcessor接口:

/**

* @author 五月的仓颉 http://www.cnblogs.com/xrq730/p/5721366.html

*/

public class InstantiationAwareBeanPostProcessorBean implements InstantiationAwareBeanPostProcessor

{

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException

{

System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInitialization()");

return bean;

}

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException

{

System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInitialization()");

return bean;

}

public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException

{

System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInstantiation()");

return true;

}

public Object postProcessBeforeInstantiation(Class> bean, String beanName) throws BeansException

{

System.out.println("Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInstantiation()");

return null;

}

public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pd, Object bean,

String beanName) throws BeansException

{

return pvs;

}

}

配置一下spring.xml:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

启动容器,观察一下运行结果为:

Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInstantiation()

Enter CommonBean's constructor

Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInstantiation()

Enter CommonBean.setCommonName(), commonName = common

Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInitialization()

Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInitialization()

Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInstantiation()

Enter InstantiationAwareBeanPostProcessorBean.postProcessBeforeInitialization()

Enter InstantiationAwareBeanPostProcessorBean.postProcessAfterInitialization()

最后三行的运行结果不去关注,看到很明显的,InstantiationAwareBeanPostProcessor作用的是Bean实例化前后,即:

1、Bean构造出来之前调用postProcessBeforeInstantiation()方法

2、Bean构造出来之后调用postProcessAfterInstantiation()方法

不过通常来讲,我们不会直接实现InstantiationAwareBeanPostProcessor接口,而是会采用继承InstantiationAwareBeanPostProcessorAdapter这个抽象类的方式来使用。

后记

如果只会写个Bean,配置在xml文件里面,注入一下,那是最最基础的Spring开发者。一个中级、高级的Spring开发者,必然会对Spring中的多个扩展点有所了解,并利用这些扩展点更好地为项目服务,使得整个代码结构更加地优雅,并且可读性、可维护性更好。

抛砖引玉,本文只是简单地介绍一些常用的Spring Bean扩展接口以及它们的简单用法,更深入的或者它们一些合适的使用场景,还需要留待网友朋友们自己去探索。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573033.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

会话控制(session、cookie)

1.session(1)session存储在服务器的(2)session每个人存一份(3)session有默认的过期时间(4)session里面可以存储任意类型的数据安全,对服务造成压力用法:1.当一个页面需要使用session的时候,需要在页面顶部加session_start();2.操作session 赋…

java 批量提交_【INSERT】逐行提交、批量提交及极限提速方法

在Oracle数据库中,不是提交越频繁越好。恰恰相反,批量提交可以得到更好的性能。这篇文章给大家简单展示一下在Oracle数据库中逐行提交于批量提交两者之间的性能差别。最后再给出一种可以极大改变性能的方法。1.创建表t_ref,并初始化880992条数…

自动化测试索引

转自:http://www.cnblogs.com/zhangfei/p/5454682.html 自动化测试全聚合 UI自动化测试:1.基础API:http://www.cnblogs.com/zhangfei/p/3158223.html2.数据驱动:http://www.cnblogs.com/zhangfei/p/5390091.htmlhttp://www.cnblog…

java中p.name_spring如何使用命名空间p简化bean的配置

这篇文章主要介绍了spring如何使用命名空间p简化bean的配置,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下一般情况下,我们是这么配置bean的:说明:cars是公用的集合Bean&…

Codeforces Round #148 (Div. 2)

A. Two Bags of Potatoes 枚举倍数。B. Easy Tape Programming (待补)C. Not Wool Sequences 考虑前缀异或和。\[answer \prod_{i1}^{n}{2^m-i}\]D. Boring Partition \(a_i\)从小到大排序,以某个\(i\)为分界点,考虑各种情况的最…

c盘java文件误删_C盘爆满怎么办,教你有选择性删除文件,恢复空间

有很多朋友说电脑c盘有很多垃圾,占着空间,还导致电脑响应变慢。还不知道能不能删除,很困扰。那么c盘文件都是什么文件呢?哪些能删除,做一次全面的清理呢?下面给大家介绍一下program Date:系统文…

SSAS parent/child dimension

ex: EmployeeKey ParentEmployeeKey FullName . 给层级命名: ParentEmployeeKey-->Properties--> NameTemplate 定义层级名称 . Browse中如果想看到FullName,EmployeeKey-->Properties-->NameColumn: FullName . 上层member不显示在下一层&…

java向另一activity输入_Activity经典实例一:两个Activity传递数据和对象

1、概述:Activity类直接或者间接地继承了Context、ContextWrapper、ContextThemeWrapper等基类,因此Activity可以直接调用它们的方法。创建一个Activity需要实现某些方法,常见的是实现onCreate(Bundle status)方法,该方法将会在Ac…

团队随笔汇总

一、团队展示 二、团队选题报告 三、第二次团队作业——预则立&&他山之石 四、UML 五、团队项目——需求规格说明书 六、第四次团队作业——系统设计 七、体系结构设计MVC 八、【Alpha版本】冲刺随笔汇总 九、第六次团队作业——Alpha冲刺之事后诸葛亮 十、随堂软工团队…

echarts3 graph java_Echarts中graph类型的运用求教

以下是百度Echarts官网上关系图的源码,但是这个关系图的node节点和edge都是静态文件里规定好的,我现在想动态实现,点击其中一个节点A然后新产生一个新节点B,并且有A和B之间的edge,就类似于百度的人物关系图谱那种动态生…

Nginx系列1之部分模块详解

1 内核模块:名称: daemon语法: daemon on |off默认值: on功能: 决定nginx 在前台执行还是后台守护进程执行的名称: Env语法: env var | varvalue默认值: 没有功能: 该指令…

java创建线程哪种方法最好_Java创建线程的三种方法比较

一般有三种方法,Thread,Runnable,Callable.Runnable和Callable的区别(1)Callable规定的方法是call(),Runnable规定的方法是run().(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得(3)call方法可以抛出异常,run方法不可以(4)运…

深入理解JSON对象

深入理解JSON对象 前面的话 json(javascript object notation)全称是javascript对象表示法,它是一种数据交换的文本格式,而不是一种编程语言,用于读取结构化数据。2001年由Douglas Crockford提出,目的是取代繁琐笨重的XML格式。本…

java内存分配模型优点_高并发实战(二)-并发基础 缓存 MESI 内存模型

左图为高速缓存 右图为多级缓存数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的快速通道。主存与高速缓存都是连接在系统总线上,当然其他组件也是在此基础上进行通信的。在高速缓存出现后不久,系统变得愈加复杂,高…

CentOS 7 安装SVN服务端

CentOS7下安装SVN服务 1. yum命令即可方便的完成安装# sudo yum install subversion 测试安装是否成功:# svnserve --version 更改svn的默认配置(更改默认的指向目录和默认端口)# sudo vim /etc/sysconfig/svnserve编辑示例:OPTIONS"-r /data/svn -…

ionic简单路由及页面传参

1)页面跳转及传参方法 angular.module(app.routes, [])//routes路由模型.config(function($stateProvider, $urlRouterProvider) {$stateProvider.state(page1, {url: /page1,//路由地址templateUrl: templates/page1.html,//实际模型文件controller: page1Ctrl,//控…

java 图片组合 分解_切分和组合图片(二)

int rows 4; //初始化有小图片的数量int cols 4;int chunks rows * cols;int chunkWidth, chunkHeight;int type;//读取图片文件File[] imgFiles new File[chunks];for (int i 0; i < chunks; i) {imgFiles[i] new File("img" i ".jpg");}//缓存…

matches()方法

java.lang包中的String类和java.util.regex包中的Pattern&#xff0c;Matcher类中都有matches()方法&#xff0c;都与正则表达式有关。下面我分别举例&#xff1a;&#xff08;字符串&#xff1a;"abc"&#xff0c;正则表达式&#xff1a; "[a-z]{3}"&…

mysql 视图 局部变量_mysql创建视图和存储过程,变量

创建视图sql>create view 视图名 as select语句;修改视图并添加别名sql>create or replace view empvu10 (employee_number,employe_name,job_title)as select empno,ename,jobfrom empwhere deptno10;删除视图drop view 视图名创建存储过程create procedure 过程名(in n…

.NET简谈事务、分布式事务处理

在本人的 “ .NET简谈事务本质论”一文中我们从整体上了解了事务模型&#xff0c;在我们脑子里能有一个全局的事务处理结构&#xff0c;消除对数据库事务的依赖理解&#xff0c;重新认识事务编程模型。 今天这篇文章我们将使用.NET C#来进行事务性编程&#xff0c;从浅显、简单…