(三)配置及用法之Spring

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的过程见文章内部。

你可能感兴趣的:(spring,AOP,bean,xml,配置管理)