Spring简介
-
spring核心
- AOP:面向切面编程,扩展功能不是修改源代码实现
- IOC:控制反转,将对象的创建交给spring
- DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。
-
一站式框架
- web层:springMVC
- service层:spring的IOC
- dao层:spring的jdbcTemplate
-
优点:
- 方便解耦、简化开发,Spring 就是一个大工厂,可以将对象创建和依赖关系的维护交给 Spring 管理
- AOP 编程的支持,Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
- 声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程
- 方便程序的测试,Spring 对 Junit4 支持,可以通过注解方便的测试 Spring 程序
- 方便集成各种优秀框架,Spring 不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz 等)的直接支持
- 降低 JavaEEAPI 的使用难度,Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,使这些 API 应用难度大大降低
IOC(xml)
使用技术:xml配置文件、dom4j解决xml、工厂设计模式、反射
- 导入jar包(略)、创建类(略)
-
配置文件:引约束、对象创建
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入schema约束 --> <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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 配置对象创建 --> <bean id="user" class="com.vo.User" scope="prototype" ></bean> </beans>
-
写代码测试对象创建
//1 加载spring配置文件,根据创建对象 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); //2 得到配置创建的对象 User user=(User) context.getBean("user"); System.out.println(user); user.add();
bean管理
-
bean标签常用属性:
- id属性:起名称,id属性值名称任意命名,不能包含特殊符号
- class属性:创建对象所在类的全路径
- name属性:功能和id属性一样的,但是在name属性值里面可以包含特殊符号
-
scope属性
- singleton:默认值,单例
- prototype:多例
- request:创建对象把对象放到request域里面
- session:创建对象把对象放到session域里面
- globalSession:创建对象把对象放到globalSession里面
-
bean的三种实例化方式:
-
使用类的无参数构造创建
<!-- ioc入门 --> <bean id="user" class="cn.itcast.ioc.User" scope="prototype"></bean>
-
使用静态工厂创建,创建静态的方法,返回类对象
public class Bean2Factory { //静态的方法,返回Bean2对象 public static Bean2 getBean2() { return new Bean2(); } }
配置文件
<!-- 使用静态工厂创建对象 --> <bean id="bean2" class="cn.bean.Bean2Factory" factory-method="getBean2"></bean>
-
使用实例工厂创建,创建不是静态的方法,返回类对象
public class Bean3Factory { //普通的方法,返回Bean3对象 public Bean3 getBean3() { return new Bean3(); } }
配置文件
<!-- 使用实例工厂创建对象 --> <!-- 创建工厂对象 --> <bean id="bean3Factory" class="cn.bean.Bean3Factory"></bean> <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
-
属性注入
创建对象时候,设置对象属性的值
-
使用set方法注入
<!-- 使用set方法注入属性 --> <bean id="book" class="cn.property.Book"> <!--name属性值:类里面定义的属性名称 value属性:设置具体的值--> <property name="bookname" value="易筋经"></property> </bean>
-
使用有参数构造注入
<!-- 使用有参数构造注入属性 --> <bean id="demo" class="cn.property.PropertyDemo1"> <!-- 使用有参构造注入 --> <constructor-arg name="username" value="小王"></constructor-arg> </bean>
代码
private String username; public PropertyDemo1(String username) { this.username = username; }
- 使用接口注入,spring不支持
对象类型属性注入
<!-- 注入对象类型属性 -->
<!-- 1 配置service和dao对象 -->
<bean id="userDao" class="cn.ioc.UserDao"></bean>
<bean id="userService" class="cn.ioc.UserService">
<!-- 注入dao对象-->
<property name="userDao" ref="userDao"></property>
</bean>
复杂数据注入
<!-- 注入复杂类型属性值 -->
<bean id="person" class="cn.property.Person">
<!-- 数组 -->
<property name="arrs">
<list>
<value>小王</value>
<value>小马</value>
<value>小宋</value>
</list>
</property>
<!-- list -->
<property name="list">
<list>
<value>小奥</value>
<value>小金</value>
<value>小普</value>
</list>
</property>
<!-- map -->
<property name="map">
<map>
<entry key="aa" value="lucy"></entry>
<entry key="bb" value="mary"></entry>
<entry key="cc" value="tom"></entry>
</map>
</property>
<!-- properties -->
<property name="properties">
<props>
<prop key="driverclass">com.mysql.jdbc.Driver</prop>
<prop key="username">root</prop>
</props>
</property>
</bean>
IOC(注解)
注解写法 @注解名称(属性名称=属性值)
类、方法、属性
1 、导入jar包、创建类(略)
3、 配置文件:约束、开启注解扫描
<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" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描,到包里面扫描类、方法、属性上面是否有注解 -->
<context:component-scan base-package="cn.entity"></context:component-scan>
<!-- 扫描属性上面的注解 -->
<!-- <context:annotation-config></context:annotation-config> -->
</beans>
@Service(value="user") // <bean id="user" class=""/>
public class User {
测试类
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();
bean管理
-
四个注解
- @Component
- @Controller :web层
- @Service :业务层
- @Repository :持久层
目前这四个注解功能是一样的,都创建对象
-
创建对象单实例还是多实例
@Service(value="user") // <bean id="user" class=""/> @Scope(value="prototype")
注入属性
Autowired、 Resource
-
创建dao和service对象
@Component(value="userDao") public class UserDao { @Service(value="userService") public class UserService {
-
在service类里面定义dao类型属性
@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用
//得到dao对象 //1 定义dao类型属性,在dao属性上面使用注解 完成对象注入 @Autowired()@Qualifier("baseDao") private UserDao userDao;
-
在service类里面定义dao类型属性
// 使用注解方式时候不需要set方法。name=注解创建dao对象 value值 @Resource(name="userDao") private UserDao userDao;
AOP
AOP是面向切面(方面)编程,扩展功能的同时不修改源代码。AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
AOP底层使用动态代理实现
- 有接口情况,使用JDK动态代理创建接口实现类代理对象
- 没有接口情况,使用cglib动态代理创建类的子类代理对象
基本术语
- Joinpoint(连接点):具体要增强的方法
- Pointcut(切入点):连接点的集合 .
- Advice(通知/增强):拦截到Joinpoint之后所要做的事情,切入切点的时机
分为:前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能) - Aspect(切面): 切点、连接点、通知所在的类为切面
- Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
- Target(目标对象):代理的目标对象(要增强的类)
- Weaving(织入):是把增强应用到目标的过程. 把advice 应用到 target的过程
- Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
操作准备
- 导包:基本的jar包、aop相关的jar包
-
配置文件,导入aop的约束
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
xml方式
在spring里面进行aop操作,使用aspectj实现。aspectj不是spring一部分,和spring一起使用进行aop操作;Spring2.0以后新增了对AspectJ支持
-
使用表达式配置切入点,常用的表达式
execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
- execution(* cn.aop.Book.add(..))
- execution( cn.aop.Book.(..))*
- execution( .(..))
- 匹配所有save开头的方法 execution( save(..))
- Aspectj的aop操作
<!-- 1 配置对象 -->
<bean id="book" class="cn.aop.Book"></bean><!--连接点-->
<bean id="myBook" class="cn.aop.MyBook"></bean><!--切面-->
<!-- 2 配置aop操作 -->
<aop:config>
<!-- 2.1 配置切入点 -->
<aop:pointcut expression="execution(* cn.aop.Book.*(..))" id="pointcut1"/>
<!-- 2.2 配置切面 把增强用到方法上面 -->
<aop:aspect ref="myBook">
<!-- 配置增强类型 method: 增强类里面使用哪个方法作为前置-->
<aop:before method="before1" pointcut-ref="pointcut1"/>
<aop:after-returning method="after1" pointcut-ref="pointcut1"/>
<aop:around method="around1" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
- 切面(MyBook)代码:
public void before1() {
System.out.println("前置增强......");
}
public void after1() {
System.out.println("后置增强......");
}
//环绕通知
public void around1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//方法之前
System.out.println("方法之前.....");
//执行被增强的方法
proceedingJoinPoint.proceed();
//方法之后
System.out.println("方法之后.....");
}
注解方式
-
创建对象
<!-- 1 配置对象 --> <bean id="book" class="cn.aop.Book"></bean> <bean id="myBook" class="cn.aop.MyBook"></bean>
-
在spring核心配置文件中,开启aop操作
<!-- 开启aop操作 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
-
在增强类上面使用注解完成aop操作
@Aspect public class MyBook { //在方法上面使用注解完成增强配置 @Before(value="execution(* cn.aop.Book.*(..))") public void before1() { System.out.println("before.............."); } }
jdbcTemplate操作
配置连接池
-
配置c3p0连接池
导入jar包,创建spring配置文件,配置连接池
<!-- 配置c3p0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 注入属性值 --> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///spring"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 创建service和dao对象,在service注入dao对象 --> <!-- 创建jdbcTemplate对象 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 把dataSource传递到模板对象里面 --> <property name="dataSource" ref="dataSource"></property> </bean> <bean id="userDao" class="cn.c3p0.UserDao"> <!-- 注入jdbcTemplate对象 --> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <bean id="userService" class="cn.c3p0.UserService"> <!-- 注入dao对象 --> <property name="userDao" ref="userDao"></property> </bean>
CRUD操作
-
增加、修改、删除,调用模板方法
public void delete() { //设置数据库信息 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///spring3"); dataSource.setUsername("root"); dataSource.setPassword("root"); //创建jdbcTemplate对象,设置数据源 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); //调用update方法 //增 String sql = "insert into user values(?,?)"; int rows = jdbcTemplate.update(sql, "lucy"); //改 String sql = "update user set password=? where usename=?"; int rows = jdbcTemplate.update(sql,"1234", "lucy"); //删 String sql = "delete from user where username=?"; int rows = jdbcTemplate.update(sql, "lucy"); System.out.println(rows); }
-
查询
-
查询某个值时候,调用queryForObject方法。自己写实现类封装数据
在dbutils时候,有接口 ResultSetHandler,dbutils提供了针对不同的结果实现类
jdbcTemplate实现查询,有接口 RowMapper,jdbcTemplate针对这个接口没有提供实现类,得到不同的类型数据需要自己进行数据封装
public void testCount() { //设置数据库信息 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///spring_day03"); dataSource.setUsername("root"); dataSource.setPassword("root"); //创建jdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); //调用方法得到记录数 String sql = "select count(*) from user"; //调用jdbcTemplate的方法 int count = jdbcTemplate.queryForObject(sql, Integer.class); System.out.println(count); }
-
查询对象,调用queryForObject方法
//3 查询返回对象 @Test public void testObject() { //设置数据库信息 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///spring_day03"); dataSource.setUsername("root"); dataSource.setPassword("root"); //创建jdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); //写sql语句,根据username查询 String sql = "select * from user where username=?"; //调用jdbcTemplate的方法实现 //第二个参数是接口 RowMapper,需要自己写类实现接口,自己做数据封装 User user = jdbcTemplate.queryForObject(sql, new MyRowMapper(), "mary"); System.out.println(user); } class MyRowMapper implements RowMapper<User> { @Override public User mapRow(ResultSet rs, int num) throws SQLException { // 1 从结果集里面把数据得到 String username = rs.getString("username"); String password = rs.getString("password"); // 2 把得到数据封装到对象里面 User user = new User(); user.setUsername(username); user.setPassword(password); return user; } }
-
查询list集合,调用query方法
//4 查询返回对象 @Test public void testList() { // ComboPooledDataSource dataSource = new ComboPooledDataSource(); // dataSource.setDriverClass("com.mysql.jdbc.Driver"); // dataSource.setJdbcUrl("jdbc:mysql:///spring_day03"); // dataSource.setUser("root"); // dataSource.setPassword("root"); //设置数据库信息 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///spring_day03"); dataSource.setUsername("root"); dataSource.setPassword("root"); //创建jdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); //写sql语句 String sql = "select * from user"; //调用jdbcTemplate的方法实现 List<User> list = jdbcTemplate.query(sql,new MyRowMapper()); System.out.println(list); } } class MyRowMapper implements RowMapper<User> { @Override public User mapRow(ResultSet rs, int num) throws SQLException { // 1 从结果集里面把数据得到 String username = rs.getString("username"); String password = rs.getString("password"); // 2 把得到数据封装到对象里面 User user = new User(); user.setUsername(username); user.setPassword(password); return user; } }
-
spring事务管理
-
基于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: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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 配置c3p0连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 注入属性值 --> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql:///spring3"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 第一步 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 注入dataSource --> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 第二步 配置事务增强 --> <tx:advice id="txadvice" transaction-manager="transactionManager"> <!-- 做事务操作 --> <tx:attributes> <!-- 设置进行事务操作的方法匹配规则 --> <tx:method name="account*" propagation="REQUIRED"/> <!-- <tx:method name="insert*" /> --> </tx:attributes> </tx:advice> <!-- 第三步 配置切面 --> <aop:config> <!-- 切入点 --> <aop:pointcut expression="execution(* cn.service.OrdersService.*(..))" id="pointcut1"/> <!-- 切面 --> <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/> </aop:config> <bean id="ordersService" class="cn.service.OrdersService"> <property name="ordersDao" ref="ordersDao"></property> </bean> <bean id="ordersDao" class="cn.dao.OrdersDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> </beans>
-
基于注解方式
<!-- 第一步配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 第二步 开启事务注解 --> <tx:annotation-driven transaction-manager="transactionManager"/>
第三步 在要使用事务的方法所在类上面添加注解
@Transactional public class OrdersService {
Junit测试配置
-
maven 配置
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.12</version> <scope>test</scope> </dependency>
-
创建BaseJunit4Test基类
用来加载配置文件、设置web环境。所有测试类,都继承该类即可
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试 @ContextConfiguration(locations={"classpath:spring.xml","classpath:spring-mvc.xml","classpath:spring-hibernate.xml","classpath:spring-ehcache.xml"}) //加载配置文件 @WebAppConfiguration("src/main/webapp") //如果加入以下代码,所有继承该类的测试类都会遵循该配置,也可以不加,在测试类的方法上 //这个非常关键,如果不加入这个注解配置,事务控制就会完全失效! //@Transactional //这里的事务关联到配置文件中的事务控制器(transactionManager = "transactionManager"),同时//指定自动回滚(defaultRollback = true)。这样做操作的数据才不会污染数据库! //@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) public class BaseJunit4Test{ }
-
测试类
public class UserTest extends BaseJunit4Test{ @Autowired //自动注入 private UserManagerService userManagerService; @Test @Transactional //标明此方法需使用事务 @Rollback(false) //标明使用完此方法后事务不回滚。true时为回滚,不会污染数据库! public void testUser(){ System.out.println("测试Spring整合Junit4进行单元测试"); AdeUser user = userManagerService.get("0"); System.out.println(user); System.out.println("------------"+user.getLoginName()); } }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。