Spring的使用
Spring配置文件是用于指导Spring工厂进行Bean生产、依赖关系注入(装配)及Bean实例分发的"图纸"。Java EE程序员必须学会并灵活应用这份"图纸"准确地表达自己的"生产意图"。Spring配置文件是一个或多个标准的XML文档,applicationContext.xml是Spring的默认配置文件,当容器启动时找不到指定的配置文档时,将会尝试加载这个默认的配置文件。
下面讲一下我在项目中所使用的两个技术set注入和拦截器。
一、Set注入
Spring有两种注入方式分别是构造注入和set注入。相应的在applicationContext.xml配置分别是:
<beans>
<bean id=”HelloWorld” class=”com.gc.action.HelloWorld” depends-on=”date”>
<property name=”msg”>
<value>HelloWorld</value>
</property>
<property name=”date”>
<ref local=”date”/>
</property>
</bean>
<bean id=”date” class=”java.util.Datte”/>
</beans>
上面是一个简单的配置文件。<bean></bean>用来指定有哪些类,<property></property>用来指定该类中有哪些变量,<value></value>用来指定一般变量的数值。<ref>用来引用其他类,Depens-on用来说明该类依赖其他类,就是说先初始化其他类,然后才能初始化这个类。这这里我们不写这个depens-on也行,因为date是其变量,初始化时候自然进行初始化了。上面的ref local表明“date”是在一个配置文件中配置的,如果是不同的则用ref bean。一般我们使用ref bean。因为ref bean即可以是在一个xml文件里配置的,也可以是在不同的xml配置的。
上面我们采用的是set方法,一般我们都采用set方式注入。
注入对java中函数有要求:
Public class HelloWorld{
Private String msg=null;//必须有msg这个变量,而且名字要和配置文件中的property中一样
Private Date date=null//同上面所描述的一样。
Public void setMsg(string msg)//必须有set+变量名首字母大写,这是规定,而且参数只有一个,类型和上面相同。则HelloWorld在创建时候会自动调用set方法,将配置文件中的value传进去。
{
this.msg=msg;
}
Public String getMsg()//必须有set+变量名首字母大写,这是规定,而且参数只有一个,类型和上面相同
{return this.msg;
this.msg=msg;
}
同理setDate,getDate();
到目前为止,我们就配置好一个完整的简单的类。
我们随便写一个类来测试;
Public class testHelloworld{
Public static void main(string[] args){
ApplicationContext actx=new FileSystemXmlApplicationContext(“config.xml”);//里面填你配置文件相对该.java的相对路径
HelloWorld helloWorld=(HelloWorld)actx.getBean(“HelloWorld”);
System.out.println(helloWorld.getMsg());
}
}
执行就会输出value中的数值 HelloWorld。
还有自动装在,就是在配置文件中我们不用写ref类型的。我们有byName,byType等。基本上大同小异。一般大型项目不推荐采用自动装配。下面我们还以上面例子进行讲解。
HelloWorld.java文件不用改动。我们只需要在配置文件中将<bean id=”HelloWorld” class=”com.gc.action.HelloWorld”autowire=”byName”>
将<property name= “date”>……….</property>这段去了。
程序运行时候,HelloWorld.java包含一个名字叫date变量,Spring就会在配置文件中找id或name是date的Bean定义,然后用它来设置date属性。
在大型的应用,不鼓励使用自动装配,因为它去除了参考依赖的透明性和清晰性。
另外还有集合的注入,如Map,Set,List等,不一一介绍,用到再百度使用。
二、拦截器
AOP意识是面向方面编程,Aspect Oriented Programming,它使开发人员可以更好的将本来不应该彼此粘合在一起的功能分开。
开发人员在编写程序时候,通常有两种代码,一种是和业务系统有关的代码,一种是和业务系统关系不大的代码,例如日志、权限、异常处理、事务处理等,以前编写代码时,是将这两种代码写在一起,这样写程序,就会出现程序中有很多相同或雷同的代码。如日志信息的输出,每个方法都要写日志,不利于程序的维护。而AOP可以实现则两类代码的分离,达到代码的复用。
AOP有三个概念:Pointcut(插入点),Advice(插入的代码)和Advisor(负责将代码插入到插入点)
Pointcut是Join Point连接点,就是我将要在那些函数,以及那些类的方法中插入我的Advice。如日志输出,Advice是负责日志输出,JoinPoint是负责业务的,我想在处理业务时候输出日志,就将处理业务的函数中插入Advice就好。
Advisor是将Advice注入到Pointcut的代码。以日志为例,也就是将日志输出这段代码插入到业务处理函数中的那部分代码。
- 如何配置AOP呢,下面用最常见的方式进行讲解:
1.1首先将一下Advice
Spring提供五种类型的Advice:Interception Around(在调用前后执行)、Before(在调用前执行),After Returning(在调用返回后执行),Throw(在抛出异常后执行)
Interception Around:
Interception Around会在JointPoint的前后执行。实现Interception Around通知的类需要实现接口MethodInterceptor,代码如下:
Public class test implements MethodInterptor{
//重写invoke
Public Object invoke(MethodInvocation invocation)throws Throwable{
System.out.println(“开始审核数据”);
Object rval=invocation.proceed();//执行JointPoint代码
System.out.printtln(“审核数据结束”);
Return rval;
}
}
Before通知只在JointPoint前执行,实现Before通知的类需要实现MethodBeforeAdvice,代码如下:
Public class test implements MethodBeforeAdvice{
//重写invoke
Public Object before(Method m,Object[]args,Object target)throws Throwable{
System.out.println(“开始审核数据”);
}
}
同理AfterReturningAdvice,方法是void afterReturning(Method m,Object[]args,Object target)throws Throwable;
ThrowsAdvice方法是void afterThrowing(RemoteException ex)throws Throwable;
1.2通过RegexpMethodPointcutAdvisor来配置Pointcut和相应的Advice,下面来个例子:
配置文件如下:
<bean ib=”logBefore” class=”com.gc.action.LogBefore”
<bean id=”mylogBeforeAdvisor” class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>//用这个配置器
<property name=”advice”><ref bean=”logBefore”/></property>//配置的advice
<property name=”patterns”><value>.*do.*</value></property>//所有以do开头的方法都是Pointcut
</bean>
我们在LogBefore.java代码:
Public classLogBefore implements MethodBeforeAdvice{
//重写invoke
Public Object before(Method m,Object[]args,Object target)throws Throwable{
System.out.println(“开始审核数据”);
}
}
我们使用自动代理即DefaultAdvisorAtoProxyCreator,使用其他代理太麻烦和使用不方便。
所以整个配置文件是:
我们写一个TimeBook.java,代码如下:
Public class TimeBook{
Public void doCheck(String name){
System.out.println(“账务关闭的相关程序正在执行。。。”);
}
}
LogBefore.java上面已经写过。
配置文件:
<bean id=”timebook” class=”com.gc.action.TimeBook”>
//使用自动代理
<bean id=”autoProxyCreator” class=”org.springframework.aop.framework.autoproxy.DaultAdvisorAtoProxyCreator”/>
<bean ib=”logBefore” class=”com.gc.action.LogBefore”
<bean id=”mylogBeforeAdvisor” class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>//用这个配置器
<property name=”advice”><ref bean=”logBefore”/></property>//配置的advice
<property name=”patterns”><value>.*do.*</value></property>//所有以do开头的方法都是Pointcut
</bean>
写一个测试类测试一下:
Public class testHelloworld{
Public static void main(string[] args){
ApplicationContext actx=new FileSystemXmlApplicationContext(“config.xml”);//里面填你配置文件相对该.java的相对路径
TimeBook book=( TimeBook)actx.getBean(“timebook”);
book.doCheck(“张三”)
}
}
执行测试程序输出:张山开始审核数据,财务关闭的相关程序正在执行。说明是在doCheck()函数执行前调用了通知。
三、数据库。我们使用自带的BasicDataSource类
<bean id="dataSourceD" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>dm.jdbc.driver.DmDriver</value></property>
<property name="url"><value>jdbc:dm://localhost:5236</value></property>
<property name="username"><value>SYSDBA</value></property>
<property name="password"><value>dnsenum</value></property>
<property name="initialSize"><value>2</value></property>
<property name="maxActive"><value>10</value></property>
<property name="minIdle"><value>20</value></property>
<property name="defaultReadOnly"><value>false</value></property>
<property name="defaultAutoCommit"><value>true</value></property>
<property name="validationQuery"> <value>select count(*) from DNS.t_zone</value></property>
</bean>
<bean id=”HelloWorld” class=”com.gc.action.HelloWorld” >
<property name=”datesource”>
<ref bean=”dataSourceD”/>
</property>
</bean>
Public class HelloWorld{
Private Datesource datesource =null;
Public void setDatesource(Datesource msg){
this. datesource =msg;
}
Public String getDatesource(){return this. datesource;}
}
写一个测试程序:
Public class testHelloworld{
Public static void main(string[] args){
ApplicationContext actx=new FileSystemXmlApplicationContext(“config.xml”);//里面填你配置文件相对该.java的相对路径
HelloWorld book=( HelloWorld)actx.getBean(“HelloWorld”);
Datesource ds=book. getDatesource();//低版本JDK使用DriverManager
Connection conn = ds.getConnection(); //就返回一个数据库连接
Statement sm = conn.createStatement(); //进行数据库操作类
String sqlString = "insert into bryanttesttable values(2,'bryant')";
Sm.execute(sqlstring);
}
}