Spring框架
一、Spring组成
1、Spring Core模块
该模块是Spring的核心容器,它实现了IoC模式和Spring框架的基础功能。在模块中包含的最重要的BeanFactory类是Spring的核心类,负责配置与管理JavaBean。它采用了Factory模式上线了IoC容器,即依赖注入。
2、Context模块
该模块继承BeanFactory(或者说Spring核心)类,并且添加了事务处理、国际化、资源加载、透明加载、以及数据校验等功能。它还提供了框架式的Bean的访问和很多企业级的功能,如JNDI访问、支持EJB、远程调用、集成模板框架、E-mail和定时任务调度等。
3、AOP模块
Spring集成了所有AOP功能,通过事务管理可以将任意Spring管理的对象AOP化。Spring提供了用标准Java语言编写的AOP框架,其中大部分内容都是根据AOP联盟的API开发。它使应用程序抛开了EJB的复杂性,但拥有传统EJB的功能。
4、DAO模块
该模块提供了JDBC的抽象层,简化了数据库厂商的异常错误(不再从SQLException继承大批代码),大幅度减少了代码的编写并且提供了对声明式和编程式事务的支持。
5、ORM映射模块
该模块提供了对现有ORM框架的支持,各种流行的ORM框架已经非常成熟,并且拥有大规模的市场(如Hibernate)。Spring没有必要开发新的ORM工具,但是为Hibernate提供了完美的整合功能,并且支持其他ORM工具。
6、Web模块
该模块建立在Spring Context基础之上,提供了Servlet监听器的Context和Web应用的上下文,为现有的Web框架如JSF、Tapestry和Struts等提供了集成。
7、MVC模块
该模块建立在Spring核心功能之上,使其拥有Spring狂阿基的所有特性,从而能够适应多种多视图、模板技术、国际化和验证服务,实现控制逻辑和业务逻辑的清晰分离
使用BeanFactory管理Bean,加载Bean配置文件的代码如下:
Resource resource1 = new ClassPathResource("applicationContext.xml"); Resource resource2 = new FileSystemResource("applicationContext.xml"); BeanFactory factory = new XmlBeanFactory(resource1); Test test = (Test) factory.getBean("test");
应用ApplicationContext:
ApplicationContext接口有3个实现类,可以实例化其中任何一个来创建Spring的ApplicationContext容器
①ClassPathXMLApplicationContext类
ApplicationContext context = new ClassPathXmlApplicationContext(String configLocation);//configLocation:指定Spring配置文件的名称和位置
②FileSystemXmlApplicationContext类
ApplicationContext context = new FileSystemXmlApplicationContext(String configLocation);
③WebApplicationContext类
WebApplicationContext是Spring的Web应用容器,在Servlet中使用该类的方法,一是在Servlet的web.xml文件中配置Spring的ContextLoaderListener监听器;二是修改web.xml配置文件,在其中添加一个Servlet,定义使用Spring的org.springframework.web.contxt.ContextLoaderServlet类。
二、Spring IoC
1、依赖注入的3中实现类型,Spring支持后两种
①接口注入
该类型基于接口将调用的与实现分离,这种依赖注入方式必须实现容器所规定的接口。使程序代码和容器的API绑定在一起,这不是理想的依赖注入方式
②Setter注入
该类型基础JavaBean的setter()方法为属性赋值,在实际开发中得到了最广泛的应用
public class User{ private String name; public String getName(){ return name; } pubilc void setName(String name){ this.name = name; } }
③构造器注入
该类型基于构造方法为属性赋值,容器通过调用类的构造方法将其所需的依赖关系注入其中
public class User{ private String name; public User(String name){ this.name=name; } }
2、依赖注入配置
①Setter注入
public class User { private String name; private Integer age; private String sex; ... //省略的setter()和getter()方法 }
<bean id="user" class="entities.User" >
<property name="name" value="无语"/>
<property name="age" value="25" />
<property name="sex" value="男" />
</bean>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); System.out.println("name:"+user.getName()+"age:"+user.getAge()+"sex:"+user.getSex());
②、构造器注入
private String name; private Integer age; private String sex; public User(String name, Integer age, String sex) { this.name = name; this.age = age; this.sex = sex; } public void printlnInfo(){ System.out.println("name:"+name+"age:"+age+"sex:"+sex); }
<bean id="user" class="entities.User" >
<constructor-arg name="name" value="哈哈" />
<constructor-arg name="age" value="26" />
<constructor-arg name="sex" value="女" />
</bean>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); user.printlnInfo();
3、引用其他Bean
三、AOP
1、AOP术语
①切面(Aspect):对象操作过程中的截面。实际上是一段程序代码,这段代码被“植入”到程序流程中。
②连接点(Join Point):对象操作过程中的某个阶段点。实际上是对象的一个操作,如对象调用某个方法、读写对象的实例或者某个方法抛出了异常。
③切入点(Pointcut): 连接点的集合,切面与程序流程的“交叉点”。
④通知(Advice):某个切入点被横切后所采取的处理逻辑,即在“切入点”处拦截程序后通过通知来执行切面。
⑤目标对象(Target):所有被通知的对象都是目标对象(也可以理解为被代理的对象),目标对象及其属性改变、行为调用和方法传参的变化被AOP所关注,AOP会注意目标对象的变动,并随时准备向目标对象“注入切面”。
⑥织入(Weaving):将切面功能应用到目标对象的过程,由代理工厂并创建一个代理对象,这个代理可以为目标对象执行切面功能。
⑦切入(Introduction):对一个已编译的类,在运行时期动态地向其中加载属性和方法。
2、AOP的简单实现
public class Target { //程序执行的方法 public void execute(String name){ System.out.println("程序开始执行:"+name); } }
public class LoggerExecute implements MethodInterceptor{ public Object invoke(MethodInvocation methodInvocation) throws Throwable { before(); //执行前置通知 methodInvocation.proceed(); //proceed()方法是执行目标对象的execute()方法 return null; } //前置通知,before()方法在invocation.proceed()之前执行,用于输出提示信息 private void before(){ System.out.println("程序开始执行!"); } }
public class Manger { //使用AOP的功能必须创建代理 public static void main(String[] args) { Target target = new Target();//创建目标对象(被代理的对象) ProxyFactory di = new ProxyFactory(); di.addAdvice(new LoggerExecute()); di.setTarget(target); Target proxy = (Target) di.getProxy();//获取代理对象 proxy.execute("AOP的简单实现");//代理执行execute()方法 } }
四、Spring的切入点
1、静态切入点
静态切入点可以为对象的方法签名,如在某个对象调用execute()方法时,这个方法即静态切入点。
2、动态切入点
3、自定义切入点
五、Aspect对AOP的支持
六、Spring持久化
1、Spring的DAO提供了如下抽象类:
JdbcDaoSupport:JDBC DAO抽象类,开发人员需要为其设置数据源(DateSource)。通过子类能获得JdbcTemplate来访问数据库
HibernateDaoSupport:Hibernate DAO抽象,开发人员需要为其配置Hibernate SessionFactory,通过其子类能够获得Hibernate实现
JdoDaoSupport:Spring为JDO提供的DAO抽象类,开发人员需要为它配置PersistenceManagerFactory,通过其子类能够获得JdoTemplate。
public class User { private String name; private Integer age; private String sex; ... }
public interface UserDao { public void insert(User user); }
public class UserDaoImpl implements UserDao { public DataSource getDataSource() { return dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } private DataSource dataSource; public void insert(User user) { String name = user.getName(); String sex = user.getSex(); Integer age = user.getAge(); Connection conn = null; Statement stmt = null; try{ conn = dataSource.getConnection(); stmt = conn.createStatement(); String sql = "INSERT INTO user(name,sex,age) values('"+name+"','"+sex+"',"+age+")"; int count = stmt.executeUpdate(sql); System.out.println(count); }catch (SQLException e){ e.printStackTrace(); }finally { try{ if(stmt!=null){ stmt.close(); } if(conn!=null){ conn.close(); } }catch (SQLException e){ e.printStackTrace(); } } } }
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mytest?useSSL=false" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> <bean id="userDao" class="dao.UserDaoImpl"> <property name="dataSource" ref="dataSource" /> </bean>
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = new User(); user.setName("小明"); user.setAge(20); user.setSex("男"); UserDao userDao = (UserDao) context.getBean("userDao"); userDao.insert(user); }
2、事务管理
Spring中的事务基于AOP实现,而Spring的AOP以方法为单位,所以Spring的事务属性是对事务应用的方法的策略描述。这些属性为传播行为、隔离级别、只读和超时属性
①编程式事务管理
在Spring中主要有两种编程式事务的是实现方法,分别使用PlatfromTransactionManager接口的事务管理器或者TransactionTemplate实现。两者各有优缺点,推荐使用TransactionTemplate实现方式,因其符合Spring的模板模式。
public class TransactionExample { private DataSource dataSource; private PlatformTransactionManager transactionManager; private TransactionTemplate transactionTemplate; ......//省略set和get方法 public void transactionOperation(){ transactionTemplate.execute(new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus transactionStatus) { Connection conn = DataSourceUtils.getConnection(dataSource); try{ Statement stmt = conn.createStatement(); //执行两次添加方法 stmt.executeUpdate("INSERT INTO user(name,sex,age) VALUES ('小强','男','26')"); int a =0; a=9/a;//人为制造异常 stmt.executeUpdate("INSERT INTO user(name,sex,age) VALUES ('小红','女','25')"); System.out.println("执行操作成功!"); }catch (Exception e){ transactionManager.rollback(transactionStatus); System.out.println("操作执行失败,事务回滚"); System.out.println("原因:"+e.getMessage()); } return null; } }); } }
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取TransactionExample TransactionExample transactionExample = (TransactionExample) context.getBean("transactionExample"); transactionExample.transactionOperation(); }
<bean id="transactionExample" class="transaction.TransactionExample"> <property name="dataSource" ref="dataSource"/> <property name="transactionManager" ref="transactionManager"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean> <!--定义事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--定义TransactionTemplate模板--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> <!--限定事务的传播行为,规定当前方法必须运行在事务中,如果没有事务,则创建一个。一个新的事务和方法一统开始,随着方法的返回或抛出异常而终止--> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/> </bean>
②声明式事务管理
声明式事务不涉及组件依赖关系,它通过AOP实现事务管理,在使用声明式事务时不需要编写任何代码即可通过实现基于容器的事务管理。Spring提供了一些可供选择的辅助类,他们简化了传统的数据库操作流程。在一定程度上节省了工作量,提高了编码效率,所以推荐使用声明式事务。
3、应用JdbcTemplate操作数据库
方法名称 |
说明 |
int QueryForInt(String sql) |
返回查询的数量,通常是聚合函数数值 |
int QueryForInt(String sql,Object[] args |
返回查询的数量,通常是聚合函数数值 |
long QueryForLong(String sql) |
返回查询的信息数量 |
long QueryForLong(String sql,Object[] args |
返回查询的信息数量 |
Object QueryforObject(String sql,Class requiredType) |
返回满足条件的查询对象 |
Object QueryforObject(String sql,Class requiredType,Object[] args) |
返回满足条件的查询对象 |
List queryForList(String sql) |
返回满足条件的对象List集合 |
List queryForList(String sql,Object[] args) |
返回满足条件的对象List集合 |
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate"); String sql = "select * from user"; List<Map<String,Object>> list = jdbcTemplate.queryForList(sql); for (Map<String, Object> objectMap : list) { String name = objectMap.get("name").toString(); String sex = objectMap.get("sex").toString(); String age = objectMap.get("age").toString(); System.out.println("name:"+name+", sex:"+sex+", age:"+age); } }
4、Spring整合Hibernate
在Spring中整合Hibernate 4 时,已不再提供HibernateTemplate和HibernateDaoSupport类,而只有一个称为LocalSessionFactoryBean的SessionFactoryBean,通过它可以实现基于注解或是XML文件来配置映射文件
Hibernate的连接和事务管理等从建立SessionFactory类开始,该类在应用程序中通常只存在一个实例。因而其底层的DataSource可以使用Spring的IoC注入,之后注入SessionFactory到依赖的对象中。
hibernate.properties文件:
#数据库驱动 hibernate.connection.driver_class = com.mysql.jdbc.Driver #数据库连接的URL hibernate.connection.url = jdbc:mysql://localhost:3306/mytest #用户名 hibernate.connection.username = root #密码 hibernate.connection.password = ******
在Spring配置文件中引入hibernate.properties文件并配置数据源dataSource
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}"/>
<property name="url" value="${hibernate.connection.url}"/>
<property name="username" value="${hibernate.connection.username}"/>
<property name="password" value="${hibernate.connection.password}"/>
</bean>
通过一个LocalSessionFactoryBean配置Hibernate,通过Hibernate的多个属性可以控制其行为。其中最重要的是mappingResources属性,通过其value值指定Hibernate使用的映射文件
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="hibernateProperties"> <props> <!--数据库连接方言--> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <!--在控制台输出SQL语句--> <prop key="hibernate.show_sql">true</prop> <!--格式控制台输出的语句--> <prop key="hibernate.format_sql">true</prop> </props> </property> <!--Hibernate映射文件--> <property name="mappingResources"> <list> <value>entities/User.hbm.xml</value> </list> </property> </bean>