Spring 也表示是一个开源框架,是为了解决企业应用程序开发复杂性由Rod Johnson创建的。框架的主要优势之一就是其分层架构。本文是Spring的配置,主要讲解的还是xml和Annotation的配置。里面涵盖了一点整合的配置,具体三大框架的整合,之后还会发表文章。之前发表的文章还很不完善,希望在以后慢慢的补充和完善下去,有不懂的或我写得不对的请留言,我们大家一起讨论一下。进入正题。
(1)Spring目前用到的包:
cglib-nodep-2.1_3.jar、commons-logging.jar、dom4j-1.6.1.jar、log4j-1.2.15.jar、spring.jar、aspectjrt.jar、aspectjweaver.jar、struts2-spring-plugin-2.2.1.1.jar、commons-dbcp.jar、commons-pool.jar
(2)applicationContext.xml的配置(一般放在WebRoot/WEB-INF文件里):
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!--在自定义的包路径里寻找匹配的Bean-->
<context:component-scan base-package="com.xxx"></context:component-scan>
<!--Bean的定义-->
<bean id="xxx" class="xxx" scope="">
//这里的scope属性很重要,在下面介绍
<property name="bean里的属性名">
<ref bean="引用的bean" />//通过已声明的Bean进行注入
//<bean id="" class=""></bean>把要注入的Bean在里面定义
//<constructor-arg><value>ABC</value></constructor-arg>构造注入
//<value>xxxx</value>设值注入
</property>
</bean>
<!-- 定义事务管理器 -->
//定义Hibernate事务管理
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>//定义注解配置事务,如果要使用注解事务,必须定义这个
<!--配置AOP-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> //使用AOP自动代理,必须定义
<aop:config>
<aop:aspect id="logsAspect" ref="logsRecord">
<aop:pointcut expression="execution(* com.xxx.service.impl.AdminLogin.login(..))" id="recordPoint" />
<aop:after-returning method="recordLogs"
returning="flag" pointcut-ref="recordPoint" />
</aop:aspect>
</aop:config>
//bean的scope属性:(1)singleton作用域:当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的恳求 ,只要id与该bean定义相匹配,则只会返回bean的同一实例。(2)prototype:prototype作用域布置的bean,每一次恳求 (将其注入到另一个bean中,或者以程序的法子 调用容器的getBean()法子)都会产生 一个新的bean实例,相当与一个new的操作。(3)request:request表现 该针对每一次HTTP恳求 都会产生 一个新的bean,同时该bean仅在当前HTTP request内有效
(4)还有session、global session等![color=red]详细使用请上网查找,一般的选择原则:有状态的bean都使用Prototype作用域,而对无状态的bean则应该使用singleton作用域。我曾经因为Action调用错误,让Spring管理Action,因为是单例模式,导致以后都出错。改为prototype之后就解决了。所以得慎用![/color]
web.xml的配置:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
//如果applicationContext.xml在src下classpath:applicationContext.xml
//如果有多个的xml,如applicationContext.xml、applicationContext-xxxx.xml在src下classpath:applicationContext*.xml,*表示:如abc*.xml匹配abc.xml、abc-xxx.xml等,同理可得。。。你懂的
接下来详解applicationContext.xml的几个主要的配置,主要使用例子来讲述,里面涵盖xml和Annotation的联合使用:
自定义的注解:
@Target(ElementType.METHOD)//定义这个注解只能用在方法之上
@Retention(RetentionPolicy.RUNTIME)//运行时
public @interface MethodAnnotation {
String value() default "";
}
AdminLogin类:
@Service//设置为Spring的组件
@Scope(value="xxx")设置作用域
public class AdminLogin implements LoginService {
@Resource//Bean属性的匹配
private HibernateUtilDao hibernateUtilDao;
@MethodAnnotation("注解测试")
public boolean login(String name, String passWord) {
boolean flag = false;
String hql = "from Admin as admin where admin.adminName=? and admin.passWord=?";
String[] params = { name, passWord };
Iterator<Object> iter = hibernateUtilDao.queryList(hql, params).iterator();
if (iter.hasNext()) {
flag = true;
ActionContext.getContext().getSession().put("userName", name);
}
return flag;
}
}
//@Resource(name="xxx")有二义性的话需设置名字匹配或type="xxx"(类型匹配),如果无二义性(所谓二义性,比如不同的bean可以实现于同一个接口)的话不需要设定,个人认为不管有没有二义性,设定name匹配比较好些。
//@Resource(name="xxx")等价于@Autowired加上@Qualifier("xxx"),好像@Autowired默认是类型匹配。还是用@Resource(name="xxx")比较好。不容易混乱
AOP的配置:
LogsRecord类,我暂且把这个类理解为“切面”
@Component//声明为Spring的组件Bean,还有@Service(业务组件)@Repository(持久化组件)@Controller(控制组件),他们的效果都是一样的,名字只是为了更好的区分他们的分层作用,如果不设定name,bean的name默认为以类名为标准,开头小写,如logsRecord
public class LogsRecord {
public void recordLogs(JoinPoint jp, boolean flag) {//JoinPoint为切入点的意思,具体用法看方法内部。flag是我们之前定义通知时设置的返回值,名字随意起,但是上下要一致。这个返回值从哪里来?就是切点方法(login)调用之后得到的返回值(login返回的是boolean)。
if (flag) {
Method[] method = jp.getTarget().getClass().getMethods();
//获得切点jp这个类里的所有方法(Admin类里的方法)
MethodAnnotation methodAnnotation = method[0]
.getAnnotation(MethodAnnotation.class);//获得method[0]方法上的注解
System.out.println(method[0].getName());
System.out.println("注解作用:" + methodAnnotation.value());
String userName = (String) ActionContext.getContext().getSession()
.get("userName");
System.out.println(userName + "在" + new Date().toString() + "进行了"
+ jp.getSignature().getName() + "操作");//jp.getSignature.getName()获得当前切点执行的方法的方法名
}
}
}
<aop:config>
<aop:aspect id="logsAspect" ref="logsRecord">//ref引用Bean,可以理解为切面,切面=切点+通知
<aop:pointcut expression="execution(* com.lrl.service.impl.AdminLogin.login(..))" id="recordPoint" />//定义切点,execute(返回值 包名.类名.方法(参数列表)),*表示匹配所有,参数里的(..)表示匹配所有参数
<aop:after-returning method="recordLogs"
returning="flag" pointcut-ref="recordPoint" />//定义通知,method为切面里的方法,returning为返回值标识(可无), pointcut-ref引用定义的切点。
</aop:aspect>
</aop:config>
用Annotation配置AOP:当然,如果不喜欢在xml中配置AOP,我们同样可以使用注解配置,代码等效如下:
@Component
@Aspect//定义为切面,必须写
public class LogsRecord {
@AfterReturning(pointcut="execution(* com.lrl.service.impl.AdminLogin.login(..))",returning="flag")//设置通知,原理和xml配置AOP一样
public void recordLogs(JoinPoint jp, boolean flag) {
System.out.println(123);
if (flag) {
Method[] method = jp.getTarget().getClass().getMethods();
MethodAnnotation methodAnnotation = method[0]
.getAnnotation(MethodAnnotation.class);
System.out.println(method[0].getName());
System.out.println("注解作用:" + methodAnnotation.value());
String userName = (String) ActionContext.getContext().getSession()
.get("userName");
System.out.println(userName + "在" + new Date().toString() + "进行了"
+ jp.getSignature().getName() + "操作");
}
}
}
//其实AOP还有很多很深的用法,这里就不一一列举。前置通知,环绕通知等用法都差不多,只是环绕通知需要一个方法环绕点。
请上网查看有关资料和文档。
Spring事务的配置:(Spring事务分为编程式事务和声明式事务),以下资料参考网上和老师的~自己全写完很累,哈哈。声明式事务使用比较方便。。
(1)每个Bean都有一个代理类
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="mySqlDateSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/lrl/entity/User.hbm.xml</value>
</list>
</property>
</bean>//之后的sessionFactory都一样,就不都写上去了。篇幅问题。。
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置DAO -->
<bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置事务管理器 -->
<property name="transactionManager" ref="transactionManager" />
<property name="target" ref="userDaoTarget" />
<property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />
<!-- 配置事务属性 -->
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans>
(2)所有Bean共享一个代理类
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
lazy-init="true" abstract="true">
<!-- 配置事务管理器 -->
<property name="transactionManager" ref="transactionManager" />
<!-- 配置事务属性 -->
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 配置DAO -->
<bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="userDao" parent="transactionBase" >
<property name="target" ref="userDaoTarget" />
</bean>
</beans>
(3)使用拦截器
<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<!-- 配置事务属性 -->
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Dao</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- 配置DAO -->
<bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
(4)面向切面的方式
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:config>
<aop:pointcut id="serviceMethods" expression="execution(*
com.zoo.dao.base.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="alter*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="merge*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="do*" propagation="REQUIRED" />
<tx:method name="attach*" propagation="REQUIRED" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
//面向于切面,比较好把~~~
(5)注解式事务
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 注解事务驱动 -->
<tx:annotation-driven transaction-manager="transactionManager" />
//注意:用注解式事务,需要在要使用的方法或类之上加上@Transactional注解,方可生效!
//使用mercy时,配置上事务,否则更新不生效。(在Service比较好)
基本的配置就这样了。如果有什么不正确的或者不完善的,请留言,谢谢。
总结:(1)主要开发过程:applicationContext.xml+web.xml
(2)如果用Annotation设置Spring组件(@Compont等),且设置属性匹配(@Resource等),那么applicationContext.xml就会省了很多代码。
(3)事务、AOP的过程见文章内部。