百度百科:Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由OP)。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。
1.基本功能core:
最常用的是解决对象的创建,以及处理对象与对象之间的依赖关系。可以控制对象的创建数量,创建的时机。
⒈功能分类:
- core: IOC (inverse of control)控制反转,把对象的创建交由spring容器来完成创建。DI (dependency injection)依赖注入,处理对象与对象之间的依赖关系。(通过set方法注入对象属性。)
- AOP 面向切面编程。比如一个程序的多个类中有相同的重复代码,这时可以假想的把程序横切,提取出重复代码,在完成业务逻辑时只需要关注非重复代码即可,在程序运行时,将重复代码动态的加载到核心代码上。可以使用spring的声明式事务,将事务控制在想控制的类中
- ORM : 提供了对主流对象关系映射的支持,比如hibernate
- dao层: spring封装了jdbc的代码,JdbcTemplate类。
- web:对控制层框架的支持,比如springmvc,struts...
- JEE:支持web service 服务,比如HttpInvoker.
<!-- 1. 默认无参数构造器
<bean id="user" class="cn.User"></bean>
-->
<!-- 2. 带参数构造器 -->
<bean id="user2" class="cn.User">
<constructor-arg index="0" type="int" value="100"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="Jack"></constructor-arg>
</bean>
<!-- 3. 工厂类创建对象 -->
<!-- # 3.1 工厂类,实例方法 -->
<!-- 先创建工厂 -->
<bean id="factory" class="cn.ObjectFactory"></bean>
<!-- 在创建user对象,用factory方的实例方法 -->
<bean id="user" factory-bean="factory" factory-method="getInstance"></bean>
getInstance方法返回的是该对象的实力,具体是单例还是多例看需求。
<!-- # 3.2 工厂类: 静态方法 -->
<!--
class 指定的就是工厂类型
factory-method 一定是工厂里面的“静态方法”
-->
<bean id="user" class="cn.ObjectFactory" factory-method="getStaticInstance"></bean>
4.属性注入的方式:
a.通过set方法注入
<bean id="userService" class="cn.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
b.p名称空间注入属性的值:spring3.0以上版本支持
格式:p:属性-ref=值
<bean id="userService" class="cn.UserService" p:userDao-ref="userDao"></bean>
<bean id="user" class="cn.UserService" p:name="xxxxx"></bean>
c.自定义构造器,使用构造器进行依赖注入
d.自动装配: 自动装配不利于后期的维护,看情况使用
default-autowire = byType 如果根据类型自动装配: 必须确保IOC容器中只有一个该类型的对象
default-autowire = byName 根据名称进行自动装配,
⒌注解:使用注解的方式完成ioc和di。
使用注解的步骤:
1)先引入context名称空间
xmlns:context="http://www.springframework.org/schema/context"
2)开启注解扫描
<context:component-scan base-package="cn.itcast.*"></context:component-scan> 指定到包,该包并且该包下的包中所有的类都会被扫描。可以使用*
创建对象以及处理对象依赖关系,相关的注解:
@Component(id) 指定把一个对象加入IOC容器,如果不制定id则默认为类名
@Repository 作用同@Component; 在持久层使用
@Service 作用同@Component; 在业务逻辑层使用
@Controller 作用同@Component; 在控制层使用
@Resource 属性注入 ,可以使用在属性上,也可以使用在set方法上。
如果多个Bean存在相同的配置信息,Spring允许定义一个父Bean,然后为其定义子Bean将自动继续父Bean中的配置信息,
子Bean也可覆盖父Bean中的配置信息。
<bean id="baseDao" class="com.jyfc.spring.core.BaseDao" abstract="true" />
<bean id="QDao" class="com.jyfc.spring.core.QDao" parent="baseDao" />
QDao会继承baseDao中所有可以继承的方法和属性。
总结:
1) 使用注解,可以简化配置,且可以把对象加入IOC容器,及处理依赖关系(DI)
2) 注解可以和XML配置一起使用。
2.AOP 面向切面编程。
代理(Proxy)是一种设计模式, 提供了对目标对象另外的访问方式;即通过代理访问目标对象。 这样好处: 可以在目标对象实现的基础上,增强额外的功能操作。(扩展目标对象的功能)。
⒈静态代理:代理实现和目标对象相同的接口,代理对象构造器接受目标对象,对需要增强的方法进行重写,其他方法调用目标对象的方法即可。
2.动态代理:
⒈proxy 使用的是jdk的类,目标对象必须实现接口。使用这个方法newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
参解释:loader 类加载器
interfaces 目标对象实现的所有接口的数组
h是代理实例的调用处理程序 实现的接口。 这是一个接口,需要重写其invoke(Object proxy, Method method, Object[] args)方法。
proxy代理的弊端,目标对象必须要实现接口才能使用,如果目标对象没有实现接口则不能使用这个方法。
⒉CGlib代理:需要导入cglib的支持包,
也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展,CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
⒊使用spring的aop框架:需要引入spring的aop包。 使用spring的aop,如果目标对象实现接口就使用jdk代理,如果目标对象没有实现接口就使用cglib代理
a.使用注解方式实现aop编程:
1.bean.xml中引入aop名称空间
2.开启注解扫描并且开启aop注解方式:
<!-- 开启aop注解方式 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
3.使用注解:
Aspect 指定一个类为切面类
@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式,使用在无参构造器上。
@Before("pointCut_()") 前置通知: 目标方法之前执行
@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
@Around("pointCut_()") 环绕通知: 环绕目标方法执行
b.使用xml的方式完成aop
步骤:
1) 引入jar文件 【aop 相关jar, 4个】
2) 引入aop名称空间
3)aop 配置
* 配置切面类 (重复执行代码形成的类)
* aop配置
拦截哪些方法 / 拦截到方法后应用通知代码
aop是spring容器中的类,<aop:around method= 指定的是aop中类的方法。
<aop:config>
<!-- 定义一个切入点表达式: 拦截哪些方法 -->
<aop:pointcut expression="execution(* cn.aop_xml.*.*(..))" id="pt"/>
<!-- 切面 -->
<aop:aspect ref="aop">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pt"/>
<!-- 前置通知: 在目标方法调用前执行 -->
<aop:before method="begin" pointcut-ref="pt"/>
<!-- 后置通知: -->
<aop:after method="after" pointcut-ref="pt"/>
<!-- 返回后通知 -->
<aop:after-returning method="afterReturning" pointcut-ref="pt"/>
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
关于切入点表达式:
<!-- 定义一个切入点表达式: 拦截哪些方法 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.*.*(..))" id="pt"/>-->
<!-- 【拦截所有public方法】 -->
<!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
<!-- 【拦截所有save开头的方法 】 -->
<!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
<!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
<!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->
<!-- 【拦截指定类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->
<!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
<!-- 【多个表达式】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 下面2个且关系的,没有意义 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 【取非值】 -->
<!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>
3.spring对jdbc的封装 JdbcTemplate没怎么用过,不过挺好用。
需要引入这两个jar:
spring-jdbc-3.2.5.RELEASE.jar
spring-tx-3.2.5.RELEASE.jar
4.spring声明式事务管理:
Spring声明式事务管理器类:
Jdbc技术:DataSourceTransactionManager
Hibernate技术:HibernateTransactionManager
xml方式实现声明式事务管理:
步骤:
1) 引入spring-aop相关的4个jar文件
2) 引入aop名称空间 【XML配置方式需要引入】
3) 引入tx名称空间 【事务方式必须引入】
<!-- #############Spring声明式事务管理配置############### -->
<!-- 配置事务管理器类 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> dataSource 是需要配置的数据源
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务增强(如果管理事务?) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- 5.3 Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
<aop:config>
<aop:pointcut expression="execution(* cn.itcast.a_tx.DeptService.*())" id="pt"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
</beans>
注解方式实现:
步骤:
1) 必须引入Aop相关的jar文件
2) bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类
3)在需要添加事务控制的地方,写上: @Transactional
@Transactional注解:
1)应用事务的注解
2)定义到方法上: 当前方法应用spring的声明式事务
3)定义到类上: 当前类的所有的方法都应用Spring声明式事务管理;
4)定义到父类上: 当执行父类的方法时候应用事务。
<!-- 事务管理器类 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast.b_anno"></context:component-scan>
<!-- 注解方式实现事务: 指定注解方式实现事务 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
事务属性:
@Transactional(
readOnly = false, // 读写事务
timeout = -1, // 事务的超时时间不限制
noRollbackFor = ArithmeticException.class, // 遇到数学异常不回滚
isolation = Isolation.DEFAULT, // 事务的隔离级别,数据库的默认
propagation = Propagation.REQUIRED // 事务的传播行为
)
事务传播行为:
Propagation.REQUIRED
指定当前的方法必须在事务的环境下执行;
如果当前运行的方法,已经存在事务, 就会加入当前的事务;
Propagation.REQUIRED_NEW
指定当前的方法必须在事务的环境下执行;
如果当前运行的方法,已经存在事务: 事务会挂起; 会始终开启一个新的事务,执行完后; 刚才挂起的事务才继续运行。
spring与其他框架的整合可以网上搜寻。
该文内容中的大部分配置是引用的。