2017.2.10-2017.2.14
Spring介绍
- 开源的轻量级框架
Spring核心主要两部分
- aop:面向切面编程,扩展功能不是修改源代码实现
ioc:控制反转
对象的创建不是通过new方式实现,而是交给Spring配置创建类对象
一站式框架
- web层:springmvc
- service层:Spring的IOC
- dao层:Spring的jdbcTemplate
Spring版本
- Hibernate5.x
- Spring4.x
Spring的ioc操作
- 将对象的创建交给spring进行管理
- ioc操作两部分
- ioc的配置文件方式
- ioc的注解方式
ioc入门
- 导入jar包
- 基本jar包
- beans
- context
- core
- expression
- 日志jar包
- log4j
- commons-logging
- 基本jar包
- 创建类,在类里面创建方法
创建Spring配置文件,配置创建类
- spring核心配置文件名称和位置不固定,建议放到src下
引入schema约束
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
配置对象创建
<bean name="user" class="cn.zcw.ioc.User"></bean>
写代码测试对象创建
//1.加载Spring配置文件 ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml"); //2.得到配置创建对象,getBean的参数为配置文件bean标签的id属性值 User user=(User) context.getBean("user"); System.out.println(user);
Spring核心配置文件没有提示
先复制约束条件的
http://www.springframework.org/schema/beans/spring-beans.xsd
- Window->Preferences->搜索“xml catalog”->add->key中输入第一步的代码->file system->在spring frameword/schema/beans中找->key type选择”Schema location”
Bean实例化的方式
- 通过无参构造创建(重点,常用)
使用静态工厂
创建静态工厂类
public static User getUser(){ return new User(); }
配置核心配置文件
<!-- 使用静态工厂方式bean实例化,class为静态工厂类全路径,factory-method为返回bean的方法名称--> <bean name="bean2" class="cn.zcw.ioc.StaticFactory" factory-method="getUser"></bean>
- 测试(与无参构造方式一样)
使用实例工厂
创建实例工厂
与静态工厂相似,只是放回bean实例的方法不是静态的
配置核心配置文件
<!-- 使用实例工厂创建对象 --> <bean name="bean3factory" class="cn.zcw.ioc.Bean3Factory"></bean> <bean name="bean3" factory-bean="bean3factory" factory-method="getBean"></bean>
- 测试(与上面的一样)
bean标签常用属性
- id属性:起名称,根据id值创建对象
- class属性:类的全路径
- name属性:与id作用相同,但是可以包括一些特殊字符
- scope属性:
- singleton:单例模式(默认)
- prototype:多例模式
属性注入
定义:在创建对象时,向类里面的属性设置
- set方法注入
- 有参构造方法
接口注入(不常用)
public interface Dao{ public void test(String name); } public class DaoImpl implements Dao{ private String name; private void test(String name){ this.name=name; } }
在Spring框架只支持前两种注入
set方法注入
- 创建类、属性(book)和属性的set方法
配置核心配置文件
<bean name="set" class="property.Set"> <!-- name:属性名称 value:属性值 --> <property name="book" value="Java ee"></property> </bean>
- 测试
构造方法注入
- 创建类和带参的构造方法(参数为:name)
配置核心配置文件
<bean name="constructor" class="property.Constructor"> <!-- name:构造方法参数名称 value:参数值 --> <constructor-arg name="name" value="zcw"></constructor-arg> </bean>
- 测试
在类中注入属性
例子:在service里面将dao作为属性
- 创建Service、Dao类,Service类中创建Dao对象属性
配置核心配置文件
<bean name="dao" class="cn.zcw.ioc.Dao"></bean> <bean name="service" class="cn.zcw.ioc.Service"> <property name="dao" ref="dao"></property> </bean>
- 测试
P名称空间(知道)
核心配置文件beans标签中加入
xmlns:p="http://www.springframework.org/schema/p"
- 创建类、属性和该属性的set方法
配置核心配置文件
<!-- p:name属性:name为P类的属性名称 --> <bean name="p" class="cn.zcw.ioc.P" p:name="P名称空间注入"></bean>
- 测试
注入复杂数据类型
- 数组
- List
- Map
Properties
<bean name="person" class="cn.zcw.ioc.Person"> <property name="arrs"> <list> <value>java</value> <value>php</value> </list> </property> <property name="list"> <list> <value>初级</value> <value>中级</value> </list> </property> <property name="map"> <map> <entry key="a" value="a"></entry> <entry key="b" value="b"></entry> </map> </property> <property name="pros"> <props> <prop key="name">张常文</prop> </props> </property> </bean>
IOC和DI区别
- IOC:控制反转,把对象创建交给spring进行配置
- DI:依赖注入,向类里面的属性中设置值
关系:依赖注入不能单独存在,需要在IOC基础之上完成操作
spring整合web项目原理
思想:把加载配置文件和创建对象的过程,在服务器启动的时候完成
实现原理:
- ServletContext对象
- 监听器
具体使用:
- 在服务器启动时,为每个项目创建一个在ServletContext对象
- 在ServletContext对象创建的时候,使用监听器可以监听到ServletContext对象再什么时候创建
- 在ServletContext对象创建的时候,加载spring配置文件,创建配置文件配置对象
- 把创建出来的对象放到ServletContext域对象里面(setAttribute方法)
- 获取对象的时候,到ServletContext域得到(getAttribute方法)
Spring的bean管理–注解
- 代码里特殊标记,使用注解完成功能
- 注解写法:@注解名称(属性名称=属性值)
- 注解可以使用在类、方法、属性上面
步骤:
添加jar包
相比ioc只需再添加aop.jar
- 创建类和方法
核心配置文件
引入schema约束
<?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" 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"> <!-- bean definitions here --> </beans>
context:component-scan标签
<!-- 开启注解扫描 base-package:到指定包里面扫描类、方法、属性上的注解 --> <context:component-scan base-package="cn.zcw"></context:component-scan>
在创建对象的类上使用注解实现
@Component(value="user") //相当于<bean id="user" class="cn.zcw.anno.User"></bean> public class User {}
创建对象的注解方式(4种)
- Component
- Controller:WEB层
- Service:业务层
- Repository:持久层
目前这四个注解功能是一样的,都是创建对象
注解注入对象属性
@Autowired
@Autowired private UserDao userDao;
@Resource(name=”“)
@Resource(name="userDao") private UserDao userDao;
配置文件和注解配合使用
- 配置文件:配置类
- 注解:属性注入
AOP概念
- AOP:面向切面编程,扩展功能不需要修改源码实现
AOP采用横向抽取机制,取代了传统纵向继承体系重复性代码
纵向机制:一个类要添加一个功能,可以继承有这个功能的父类,在方法中调用父类方法解决
AOP原理
AOP术语
- Joinpoint连接点:在类里面那些方法可以被增强,这些方法称为连接点。
- 切入点:在类里面可以有很多的方法被增强,比如实际操作中,只是增强了类里面的add方法,则add方法就是一个切入点。实际增强的方法称为切入点。
通知/增强:增强的逻辑,称为增强。比如扩展日志功能,这个日志功能称为增强。
- 前置通知:在方法之前执行
- 后置通知:在方法之后执行
- 异常通知:方法出现异常执行
- 最终通知:在后置通知之后执行
- 环绕通知: 在方法之前和之后执行
切面:把增强应用到具体方法上面的过程–把增强应用到切入点的过程
Spring的AOP操作
- 在Spring里面进行AOP操作,使用aspectj实现
- aspectj不是Spring一部分,和Spring一起使用进行AOP操作
- Spring2.0以后新增了aspectj支持
- 使用aspectj实现AOP有两种方式
- 基于aspectj的xml配置
- 基于aspectj的注解方式
AOP操作准备
- 除了导入基本jar包之外,还需要导入AOP相关的jar包
- aopalliance.jar
- aspectjweaver.jar
- spring-aop.jar
- spring-aspects.jar
创建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: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"> <!-- bean definitions here --> </beans>
- 创建增强类(MyBook)和被增强类(Book)
使用表达式配置切入点:execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
- execution(* cn.zcw.aop.add(..))
- execution(* cn.zcw.aop.*(..))
- execution(* .<..>)
- 配置所有save开头的方法:execution(save(..)
核心配置文件
<?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: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"> <!-- bean definitions here --> <bean id="book" class="cn.zcw.aop.Book"></bean> <bean id="myBook" class="cn.zcw.aop.MyBook"></bean> <!-- 配置aop操作 --> <aop:config> <!-- 配置切入点 --> <aop:pointcut expression="execution(* cn.zcw.aop.Book.*(..))" id="pointcut1"></aop:pointcut> <!-- 配置切面:把增强应用到方法上 --> <aop:aspect ref="myBook"> <!-- 配置增强类型 method:增强类里面使用哪个方法作为前置 --> <aop:before method="before" pointcut-ref="pointcut1"></aop:before> </aop:aspect> </aop:config> </beans>
- 测试
AOP注释操作
核心配置文件,开启aop操作
<!-- 开启aop操作 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
为类、方法添加注释
@Aspect public class MyBook { @Before(value="execution(* cn.zcw.aop.Book.*(..))") public void before(){ System.out.println(".......前置方法......"); } }
log4j介绍
- 可以通过log4j查看程序运行过程中更详细的信息
使用
- 导入log4j的jar包
- 复制log4j的配置文件(log4j.properties),复制到src下面
设置日志级别
- info:基本的信息
- debug:更详细的信息
Spring的jdbcTemplate操作
jdbcTemplate对jdbc进行封装
- 导入jar包
- spring-tx.jar
- spirng-jdbc.jar
添加操作:
//设置数据库信息
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring");
dataSource.setUsername("root");
dataSource.setPassword("951029");
//创建jdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="insert into user values(?,?,?)";
//调用jdbcTemplate对象里面的方法实现操作
int rows=jdbcTemplate.update(sql,"1","zcw","666");
System.out.println(rows);
修改操作:
//设置数据库信息
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring");
dataSource.setUsername("root");
dataSource.setPassword("951029");
//创建jdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="update user set password=? where username=?";
//调用jdbcTemplate对象里面的方法实现操作
int rows=jdbcTemplate.update(sql,"password","zcw");
System.out.println(rows);
删除操作:
//设置数据库信息
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring");
dataSource.setUsername("root");
dataSource.setPassword("951029");
//创建jdbcTemplate对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="delete from user where password=?";
//调用jdbcTemplate对象里面的方法实现操作
int rows=jdbcTemplate.update(sql,"password");
System.out.println(rows);
查询返回单值
String sql="select count(*) from user";
//调用jdbcTemplate对象里面的方法实现操作
//queryForObject(sql语句,返回值的class);
int rows=jdbcTemplate.queryForObject(sql, Integer.class);
查询返回对象
自己要写一个类来封装返回的数据。
核心代码:
//创建jdbcTemplate对象 JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource); String sql="select * from user where username=?;"; //调用jdbcTemplate对象里面的方法实现操作 User user=jdbcTemplate.queryForObject(sql, new MapperUser(), "zcw");
封装类代码:
class MapperUser implements RowMapper{ @Override public Object mapRow(ResultSet rs, int num) throws SQLException { //从结果集中把数据得到 int id=rs.getInt("id"); String username=rs.getString("username"); String password=rs.getString("password"); //将数据封装到对象中 User user=new User(); user.setId(id); user.setUsername(username); user.setPassword(password); return user; } }
查询返回对象集合
封装类与查询返回对象的相同
核心代码:
List<User> user=jdbcTemplate.query(sql, new MapperUser());
dao层使用jdbcTemplate(注入过程)
- 导入jar包
- c3p0.jar
- mchange-connect.jar
- 创建service、dao类
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: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">
</beans>
声明事务管理(xml配置)
配置事务管理器
<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> <!-- 设置进行事务操作的方法匹配规则 这里对所有以account开头的方法进行设置 --> <tx:method name="account*"/> </tx:attributes> </tx:advice>
配置切面
<aop:config> <!-- 切入点 --> <aop:pointcut expression="execution(* cn.zcw.c3p0.ServiceUser.*(..))" id="pointcut1"/> <!-- 切面 --> <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/> </aop:config>
声明事务管理(注解方式)
声明事务管理器
<bean id="transactionManager" class=" org.springframework.jdbc.datasource.DataSourceTransactionManager" > <!-- 注入dataSource --> <property name="dataSource" ref="dataSource"></property> </bean>
开启事务注解
<tx:annotation-driven transaction-manager="transactionManager"/>
在需要被事务管理的类上写上@transactional标签
@Transactional public class ServiceUser { }