一、专业术语
- 侵入式设计
引入框架,对现有的类的结构有影响,即需要实现或继承某些特定类。如:Struts框架
- 非侵入式设计
引入框架,对现有的类结构没有影响。如:Hibernate、Spring
- 控制反转(IoC)
控制反转(Inversion on Control 、IoC):把对象的创建交给外部容器完成。
- 依赖注入(DI)
依赖注入(dependency injection):处理对象间的依赖关系
- IoC和DI的区别
控制反转:解决对象创建的问题【对象创建交给其他类】
依赖注入:解决类与类紧耦合的问题。
例如,类A依赖于类B,常规的做法是在A中直接创建B的对象,然后再调用B对象的方法;控制反转就是将创建B对象的实例化交给第三方实现;然后再创建类B的操作接口I,并在A中创建接口I的对象,最后再由第三方将B的实例注入给A中的接口I的对象。这样实例化B类对象的控制权就由A交给了第三方,同时也解决了类A和类B紧耦合的问题。
- AOP
面向切面编程(Aspect Oriented Programming)是软件编程思想发展到一定阶段的产物,是面向对象编程的有益补充。AOP一般适用于具有横切逻辑的场合,如访问控制、事务管理、性能监测等。面向切面编程简单地说就是在不改变源程序的基础上为代码段增加新的功能,对代码段进行增强处理。
- 横切逻辑
在业务系统中,总有一些散落、渗透到系统各处且不得不处理的事情,这些穿插在既定业务中的公共操作就是所谓的横切逻辑,也称为切面。
- 增强处理
在目标方法执行前后进行的操作或执行的功能就是增强处理。
- 切点
可以插入增强处理的目标方法就是所谓的切点。
二、Spring简介
Spring框架可以解决对象创建以及对象之间依赖关系的一个轻量级框架。Spring是一个全面的、企业应用开发一站式的解决方案,Spring贯穿表现层、业务层、持久层。但是Spring仍然可以和其他的框架无缝整合。
三、Spring Jar包介绍
- org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现
- org.springframework.asm——spring3.0开始提供自己独立的asm jar包
- org.springframework.aspects——Spring提供的对AspectJ框架的整合
- org.springframework.beans——所有应用都用到,包含访问配置文件,创建和管理bean等。
- org.springframework.context.support——Spring context的扩展支持,用于MVC方面
- org.springframework.context——提供在基础IOC功能上的扩展服务,此外还提供许多企业级服务的支持,有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持。
- org.springframework.core——Spring的核心工具包,其他包依赖此包
- org.springframework.expression——Spring表达式语言
- org.springframework.instrument.tomcat——Spring对tomcat连接池的集成
10.org.springframework.instrument——Spring对服务器的代理接口
11.org.springframework.jdbc——对JDBC 的简单封装
12.org.springframework.jms——为简化jms api的使用而做的简单封装
13.org.springframework.orm——整合第三方的orm实现,如hibernate,ibatis,jdo,jpa等
14.org.springframework.oxm——Spring对于object/xml映射的支持,可以让JAVA与XML来回切换
15.org.springframework.test——对JUNIT等测试框架的简单封装
16.org.springframework.transaction——为JDBC,HIBERNATE,JDO,JPA提供一致的声明式和编程式事务管理
17.org.springframework.web.portlet——Spring MVC的增强
18.org.springframework.web.servlet——对J2EE6.0 servlet3.0的支持
19.org.springframework.web.struts——整合对struts框架的支持,更方便更容易的集成Struts框架。
20.org.springframework.web——包含Web应用开发时,用到Spring框架时所需的核心类。
21.Org.springframework.web.mvc——包含SpringMVC应用开发时所需的核心类。
注意:core、beans、expression、context是Spring的核心jar包。使用Spring时必须导入commons-logging-*.jar包。
四、applicatonContext.xml - bean配置详解
- Spring相关的命名空间介绍
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> |
- bean相关的配置
<!-- IOC容器的配置: 要创建的所有的对象都配置在这里--> <bean id="user" class="com.baidu.controller.User" init-method="init_user" destroy-method="destroy_user" scope="singleton" lazy-init="false"> </bean> <!-- 带参数构造器 --> <bean id="user2" class="cn.itcast.b_create_obj.User"> <constructor-arg index="0" type="int" value="100"></constructor-arg> <constructor-arg index="1" type="java.lang.String" value="Jack"></constructor-arg> </bean> |
对象的创建(单例,多例)
scope="singleton" 单例(默认值)【service/dao/工具类建议使用】
scope="prototype" 多例【action/controller对象建议使用】
什么时候创建
scope="singleton" 启动时(容器初始化之前),就已经创建了bean,整个应用只有一个
scope="prototype" 用到对象时,才创建该对象。
是否延迟创建
lazy-init="false" 默认值,不延迟,在启动时就创建对象
lazy-init="true" 延迟初始化,在用到对象的时候才创建(只对单例有效)
创建对象之后,初始化/销毁
Init-method="init_user" 对应对象的init-user方法,在对象创建之后执行
destroy-method="destroy_user" 在调用容器(容器实现类)对象的destroy方法时候执行。
- 对象依赖关系(DI相关)
依赖注入的几种实现方式:
n 通过构造函数
n 通过set方法给属性注入值
n p 名称空间
n 自动装配(了解)
n 注解
<!-- 通过set方法进行注入 --> <bean id="userService" class="com.baidu.c_property.UserService"> <property name="userDao" ref="userDao"></property> </bean> <!-- 通过p命名空间进行注入其他bean --> <bean id="userService" class="com.baidu.c_property.UserService" p:userDao-ref="userDao"></bean> <!-- 通过p命名空间进行注入普通类型值 --> <bean id="user" class="com.baidu.c_property.User" p:name="Jack0001"></bean> <!-- 通过构造方法注入(构造方法包含1个参数) --> <bean id="userService" class="com.baidu.spring.service.UserService"> <constructor-arg type="com.wskj.spring.dao.UserDao"> <ref bean="userDao1"/> </constructor-arg> </bean> |
注意:通过p命名空间注入其他bean时,格式为:
p:属性名-ref="bean的id"
p:属性="属性值"
- 自动装配
可以在bean节点上添加autowire属性实现依赖属性的自动注入。通过为bean设置autowire后,就不用再通过构造函数、set方法、p命名空间设置依赖关系了,这样就可以大大的简化配置的代码。可以在bean节点上单独为某个bean设置装配方式,也可以在beans节点上设置所有bean的默认装配方式(default-autowire)。
自动装配方式包括:
n no:不适用自动装配
n byType:根据类型进行装配
n byName:根据bean名称进行装配
n constructor:通过构造参数进行装配
五、处理增强
- 处理增强的类型
l 前置增强MethodBeforeAdvice
l 后置增强AfterReturningAdvice
l 环绕增强MethodInterceptor
l 抛出异常增强ThrowsAdvice
- 实现增强的3种方式
l 通过接口实现增强
n 前置增强的接口为:MethodBeforeAdvice
n 后置增强的接口为:AfterReturningAdvice
n 环绕增强的接口为:MethodInterceptor
n 抛出异常增强的接口为:ThrowsAdvice
l 通过注解实现增强
l 通过Scheme配置实现增强
- 通过接口实现增强
<aop:config> <aop:pointcut expression="execution(public void *User())" id="addoptpointcut"/> <aop:advisor advice-ref="logbefore" pointcut-ref="addoptpointcut" /> </aop:config>
<aop:config> <aop:pointcut expression="execution(* spring_basic.UserService.*(..))" id="userServiceOptPointcut"/> <!-- <aop:advisor advice-ref="exceptionAdvice" pointcut-ref="userServiceOptPointcut" /> --> <aop:advisor advice-ref="logger" pointcut-ref="userServiceOptPointcut" /> </aop:config> |
- 通过注解实现增强
前置增强
@Before("execution(* service.*.*(..))")
后置增强
@AfterReturning(pointcut="execution(* service.*.*(..))", returning="result")
异常抛出增强
@AfterThrowing(pointcut="execution(* service.*.*(..))", throwing="ex")
环绕增强
@Around("execution(* service.*.*(..))")
注意:还需要在applicationContext.xml文件中添加如下配置
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 通过Scheme配置实现增强
首先:添加普通的类,里面按要求编写方法
public class Logger { public void before(JoinPoint jp){ } public void after(JoinPoint jp, Object result){ } public void aterThrowing(JoinPoint jp, Exception ex){ } public Object aroundExecute(ProceedingJoinPoint pjp) throws Throwable{ } } |
其次:在applicationContext.xml中配置aop-aspect相关的配置
<aop:config> <aop:pointcut expression="execution(* service.*.*(..))" id="optpointcut"/> <aop:aspect ref="mylogger"> <aop:before method="before" pointcut-ref="optpc" /> <aop:after-returning method="after" returning="result" pointcut-ref="optpc" /> <aop:after-throwing method="aterThrowing" throwing="ex" pointcut-ref="optpc" /> <aop:around method="aroundExecute" pointcut-ref="optpointcut"/> </aop:aspect> </aop:config> |
六、拆分Spring配置文件
n 方式一:在web.xml文件中加载多个spring配置文件
<!-- spring监听器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml,classpath:applicationContext-dao.xml, classpath:applicationContext-service.xml,classpath:applicationContext-action.xml, </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> |
n 方式二:通配符方式加载多个spring配置文件
<!-- spring监听器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml, classpath:applicationContext-*.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> |
n 方式三:使用import加载其他spring配置文件
<import resource="applicationContext-dao.xml" /> |
七、SSH框架整合
- 添加jar包
- 在web.xml文件中添加spring和struts2相关的配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>ssh_template</display-name> <!-- struts2的核心控制器 - 过滤器 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring监听器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml, classpath:applicationContext-*.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<!-- openSessionViewFilter解决懒加载问题 --> <filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>singleSession</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>openSessionInViewFilter</filter-name> <url-pattern>*.do,*.action</url-pattern> </filter-mapping>
<!-- spring解决中文乱码的过滤器 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<!--配置欢迎页面--> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app> |
- 配置struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts> <!-- 是否启用动态方法调用 --> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /> <!-- 配置strust2的对象工厂,使用Spring来管理对象的创建 --> <constant name="struts.objectFactory" value="spring"/> <!-- 让struts2始终先考虑spring的自动装箱 --> <constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true" /> <package name="default" namespace="/" extends="struts-default"> <!--通配符配置action--> <action name="*_*" class="com.tencent.qqzone.controller.{1}Action" method="{2}"> <result name="input" type="dispatcher">/pages/{1}/{2}.jsp</result> <result name="list" type="dispatcher">/pages/{1}/{2}.jsp</result> <result name="listAction" type="redirectAction">{1}_list</result> </action> </package> </struts> |
- 配置applicationContext.xml
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<!-- 加载属性文件 --> <context:property-placeholder location="classpath:database.properties"/> <!-- 创建dataSource --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="driverClass" value="${jdbc.driverClassName}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <!-- 连接池中最大的连接数量 --> <property name="maxPoolSize" value="40"></property> <!-- 连接池中最少的连接数量 --> <property name="minPoolSize" value="3"></property> <!-- 连接池中初始的连接数量 --> <property name="initialPoolSize" value="5"></property> <property name="maxIdleTime" value="20"></property> </bean> <!-- sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <!-- 设置数据源 --> <property name="dataSource"> <ref bean="dataSource" /> </property> <!-- 设置hibernate的配置文件 --> <property name="configLocation" value="classpath:hibernate.cfg.xml"/> <!-- hibernate如果使用的注解方式,则需要添加下面的配置。用途:自动扫描注解方式配置的hibernate类文件 --> <property name="packagesToScan"> <list> <value>com.wskj.ssh.entity</value> </list> </property> </bean> <!-- 自动扫描包中的注解 --> <context:component-scan base-package="com.tencent.qqzone"></context:component-scan> <!-- 事务 --> <!-- 1.配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 2.配置事务增强 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 定义事务传播属性 --> <tx:attributes> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="edit*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="new*" propagation="REQUIRED" /> <tx:method name="set*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="change*" propagation="REQUIRED" /> <tx:method name="get*" propagation="REQUIRED" read-only="true" /> <tx:method name="query*" propagation="REQUIRED" read-only="true" /> <tx:method name="find*" propagation="REQUIRED" read-only="true" /> <tx:method name="load*" propagation="REQUIRED" read-only="true" /> <tx:method name="search*" propagation="REQUIRED" read-only="true" /> <tx:method name="*" propagation="REQUIRED" read-only="true" /> </tx:attributes> </tx:advice> <!-- 3.配置事务的切入点和增强 --> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* com.tencent.qqzone.service..*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" /> </aop:config> </beans> |
- 配置hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 配置hibernate方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="jdbc.batch_size">20</property>
<property name="connection.autocommit">true</property>
<!-- 显示sql语句 -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- 编码,解决和数据库操作时的中文乱码问题 -->
<property name="connection.useUnicode">true</property>
<property name="connection.characterEncoding">UTF-8</property>
<!-- 在下面添加hibernate的实体映射文件 -->
<mapping resource="com/tencent/qqzone/pojo/LogCategory.hbm.xml" />
<mapping resource="com/tencent/qqzone/pojo/LogInfo.hbm.xml" />
</session-factory>
</hibernate-configuration>