您的位置:首页 > 编程语言 > Java开发

Spring

2016-07-28 18:50 435 查看
Spring

================================================================
一、简介

1.IoC(inversion of control)

  控制反转(bean容器/集成其它框架),也就是说,控制权由对象转移到spring,对象自己变成了被动的接受。

  DI(dependency injection)依赖注入,指在运行期,由外部容器动态地将依赖对象注入到组件中。

2.AOP(aspect oriented programming)

  面向切面编程,Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如日志(log)和事务(transaction)管理)进行内聚性的开发。

  应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

在项目中引入Spring可以带来的好处:

l、降低组件之间的耦合度,实现软件各层之间的解耦合

2、可以使用容器提供的众多服务,如:事务管理服务

3、作为一个Bean容器,提供单例模式支持,开发人员不再需要自己编写实现代码。

4、容器提供了AOP技术,利用它很容易实现如权限拦截、日志管理、运行期监控等功能

5、容器提供的众多辅助类,使用这些类能够加快应用的开发,如JdbcTemplate、HibernateTemplate

6、Spring对于主流的应用框架提供了集成支持,如:集成Mybatis、Struts等,这样更便于应用的开发

设计模式 + 反射 + xml 、注解

============================================================================================

几个常用jar包简介:

org.springframework.core——Spring的核心工具包,其他包依赖此包

org.springframework.beans——所有应用都用到,包含访问配置文件,创建和管理bean等,是Spring IOC的基础实现

org.springframework.spring-tx--事务

org.springframework.context——提供在基础IOC功能上的扩展服务,此外还提供许多企业级服务的支持,

                                                           有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持

org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现

org.springframework.jdbc——对JDBC的简单封装

org.springframework.orm——整合第三方的orm实现,如hibernate,ibatis,jdo以及spring 的jpa实现

org.springframework.web——包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、

                                                      Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类

org.springframework.spring-webmvc——包括框架的Servlets,Web MVC框架,控制器和视图支持

二、依赖注入
1.Set注入
package com.taiyang.service;
public class UserService {

//注入对象userDao
private UserDao userDao;

//一定要写被注入对象的set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

}
<!--配置bean,配置后该类由spring管理-->  
<bean name="userService" class="com.taiyang.service.UserService">
<!--(1)依赖注入,配置当前类中相应的属性-->
<property name="userDao" value="com.taiyang.dao.impl.UserDaoImpl"></property>
</bean>
2.构造器注入
public class UserService {

//注入对象userDao
private UserDao userDao;
private User user;

public UserService(UserDao userDao, User user){
this.userDao = userDao;
this.user = user;
}

public void save(){
user.setName("sun");
springDao.save(user);
}
}

<bean name="userService" class="com.taiyang.service.UserService">
<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->
<constructor-arg ref="userDao"></constructor-arg>
<constructor-arg ref="user"></constructor-arg>
</bean>
<bean name="userDao" class="com.taiyang.dao.impl.UserDaoImpl"></bean>
<bean name="user" class="com.taiyang.vo.User"></bean>  
<constructor-arg index="0" ref="userDao"></constructor-arg> 设置参数位置

<constructor-arg type="java.lang.String" ref=""/> 设置参数类型

3.接口注入
public class UserService {
private UserDao userDao;

public void saveUser() {
Ojbect obj = Class.forName(com.taiyang.dao.impl.UserDaoImpl).newInstance();
userDao = (UserDao)obj;
userDao.save(...);
}

}


UserService依赖于UserDao的实现,如何获得UserDao实现类的实例?

传统的方法是在代码中创建UserDao实现类的实例,并将其赋予userDao,

这样一来,UserService在编译期即依赖于UserDao的实现.

为了将调用者与实现者在编译期分离,我们根据预先在配置文件中设定的实现类的类名(com.taiyang.dao.impl.UserDaoImpl),

动态加载实现类,并通过UserDao强制转型后为UserService所用,这就是接口注入的一个最原始的雏形.

三种注入方式比较:

A.接口注入:

接口注入模式因为具备侵入性,它要求组件必须与特定的接口相关联,因此并不被看好,实际使用有限。

B.Setter注入:

依赖关系更加直观,符合javabean的形式;

如果依赖关系较为复杂,那么构造器注入模式的构造函数也会相当庞大,而Setter方式注入更为简洁;

如果用到了第三方类库,可能要求我们的组件提供一个默认的构造函数,此时构造子注入模式也不适用。  

C.构造器注入:

在构造期间完成一个完整的、合法的对象。

所有依赖关系在构造函数中集中呈现。

依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。

只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中。

参考:http://blog.csdn.net/qiulongtianshi/article/details/7748227

三、事务

1.声明式事务

三层结构action--service--dao

一般在service层配置事务
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 配置声明式事务 -->
<aop:config>
<aop:pointcut id="baseServiceMethods"
expression="execution(* com.taiyang.service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="baseServiceMethods" />
</aop:config>

<!-- 配置事务的传播特性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="query*" propagation="SUPPORTS" read-only="true" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
2.注解式事务(编程式事务)

<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional
@Service("userService")
public class UserService {

@Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")
public void addUser(User user) throws Exception {
this.save(user);
}

@Transactional(readOnly=true)
public void selectUser() {

}

}

四、切面编程
<!--Controller 日志Aspect-->
<bean id="controllerAspectBean" class="com.taiyang.aspect.ControllerAspect" /><!--切面编程类-->
<aop:config>
<aop:aspect id="controllerAspect" ref="controllerAspectBean">
<aop:pointcut expression="execution(public * com.taiyang.controller..*.*(..))" id="controllerLog"/> <!--切面-->
<aop:before method="before" pointcut-ref="controllerLog"/><!--切入点-->
<aop:around method="around" pointcut-ref="controllerLog"/>
</aop:aspect>
</aop:config>
package com.taiyang.aspect;

public class ControllerAspect {

/**
* 日志
* @Title: before
* @Description: 请求前
* @param JoinPoint
*/
public void before(JoinPoint joinpoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
logger.info("请求的接口:"+request.getRequestURL());
StringBuilder psb = new StringBuilder("接口请求参数:[ ");
for(Object key : request.getParameterMap().keySet()){
psb.append(key).append("=").append(request.getParameter(key.toString())).append(",");
}
psb.deleteCharAt(psb.length()-1).append("]");
logger.info(psb.toString());
}

/**
* 可以在这里判断用户权限
* 验证类或方法上的注解
* 跨域支持/加压缩等处理
* @Title: around
* @Description: 环绕通知
* @param ProceedingJoinPoint
*/
public Object around(ProceedingJoinPoint pjp)  {
long start = System.currentTimeMillis();//开始时间
String callback = null;//支持跨域
try{
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
callback = request.getParameter("callback");
//Auth判断
ResultMap rmAuth = this.AuthCheck(pjp,request);
if(((Integer)rmAuth.get("resultCode")) != BusinessStatusEnum.SUCCESS.getStatus()){
return jsonCallback(callback,rmAuth);
}
Object obj = pjp.proceed();
long end = System.currentTimeMillis();//结束时间
logger.info("around " + pjp + "\tUse time : " + (end - start) + " ms!");
return normalCallback(callback, obj);
}catch (Throwable t){
long end = System.currentTimeMillis();//结束时间
logger.info("around " + pjp + "\tUse time : " + (end - start) + " ms!");
logger.error("around()方法出错,错误信息:{}", t);
return jsonCallback(callback,new ResultMap(BusinessStatusEnum.FAIL));
}
}
private Object jsonCallback(String callback,ResultMap resultMap){
JsonMapper jm = JsonMapper.buildNonNullBinder();
if(StringUtils.isNotBlank(callback)){//支持跨域
return callback + "("+ jm.toJson(resultMap) +")";
}else{
return jm.toJson(resultMap);
}
}
private Object normalCallback(String callback,Object obj){
if(StringUtils.isNotBlank(callback)){//支持跨域
return callback + "("+ obj +")";
}else{
return obj;
}
}

//Auth注解--判断用户合法
private ResultMap AuthCheck(ProceedingJoinPoint pjp, HttpServletRequest request) throws NoSuchMethodException {
// 方法级别的注解
//拦截的实体类
Object target = pjp.getTarget();
//拦截的方法名称
String methodName = pjp.getSignature().getName();
//拦截的放参数类型
Class[] parameterTypes = ((MethodSignature)pjp.getSignature()).getMethod().getParameterTypes();
Class[] clazzs = target.getClass().getInterfaces();
//1.获取类
Class clazz = target.getClass();
if (clazzs != null && clazzs.length > 0){
clazz = clazzs[0];
}
//2.获取方法
Method m = clazz.getMethod(methodName, parameterTypes);
// 方法级别的注解
if(m!=null && m.isAnnotationPresent(Auth.class)){
ResultMap rm = this.validate(request);
return rm;
}
// 类级别的注解
/*Auth can = (Auth) clazz.getAnnotation(Auth.class);
if(can!=null && StringUtils.isNotBlank(can.value())){
if(request!=null){
String param = request.getParameter("param");
System.out.println(param + "---===");
ResultMap rm = this.validate_new(request);
}
}*/
return new ResultMap(BusinessStatusEnum.SUCCESS);
}
/**
* 验证用户
* @return
*/
private ResultMap validate(HttpServletRequest request) {
//todo 校验用户是否登录状态
return new ResultMap(BusinessStatusEnum.SUCCESS);
}
}

五、配置文件介绍

<import resource="spring-import-tasks.xml"/> 引入其它xml配置文件

<context:property-placeholder location="classpath:jdbc.properties" /> 引入其它properties配置文件

<util:properties id="properties" location="classpath:jdbc.properties"/>

<context:component-scan base-package="com.taiyang.service" /> 扫描包,实现Bean的自动载入

 在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,

 如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean

 注意:如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息