1.Spring是什么?
Spring就是用来解决对象的创建和对象之间的依赖关系的 这样一门技术。
Spring能干什么?
1>:创建对象
2>:依赖关系
3>:为service提供事务
4>:整合我们的传统开发框架
2.事务:
1>:粗粒度事务
只能够对方法进行添加事务 这种称为粗粒度事务(Spring的事务只能够是粗粒度的事务)
以后我们在给访问数据库添加事务的时候是不会将事务写到dao层上的, 因为一个动作是否完成取决于业务逻辑是否完成 ,所以事物都是添加在service上的
2>:细粒度事务
就是一个事务能够对我们的程序的某几行提供的事务
3>:事务的分类
1>:本地事务
就是只是对一个数据库添加的事务, 我们目前学习的都叫本地的事物
2>:全局事务
举例:银行转账 --中国银行给建设银行转钱 。 这个是两个不同的数据库 ,要同时保证在这两 个表中的操作能够顺利的进行,就必须要使用全局事务
3.Spring的模块图(7个)
1.Spring AOP模块
AOP:面向切面的编程
就是将重复代码抽取出来形成切面类 ,然后当我们程序运行的时候,通过 动态代理或者cglib代理来完成代码的自动植入 的这样一个编程思想 就叫做面向切面的编程
2.Spring ORM模块
主要是提供了对Hibernate/MyBatis/JDO其他ORM框架整合的支持(对象关系映射)
3.Spring DAO模块
这个模块实际上是 Spring提供的一个dao层的解决方案(dbutils这种)
4.Spring WEB模块
这个是Spring提供的对web的支持
5.Spring Context模块
Spring提供的一个对上下文的支持
6.Spring WEB MVC模块
这个模块实际上就是传说中的 Spring MVC
7.Spring Core模块
在我们的Spring中提供了两个思想: IOC / DI
IOC----->表示的是控制反转(inversion of control)
DI ----->依赖注入 (dependcy injecte)
反转的是什么?
1>:以前我们在使用MVC模式来进行开发的时候 service对象是谁创建的?dao对象是谁创建的? 以前我们要使用这个任意类的对象 --->自己通过程序去new一个
2>:学习了IOC之后那么以后我们的对象的创建就不是我们去完成了,而是由Spring的IOC容器去完成
那么反转的是什么? 反转的是创建对象的这个权利-----------以前我们自己创建,现在Spring的IOC容器去给我们创建;
具体控制的是什么? 控制的是创建对象。
依赖注入:注入的是什么?
依赖表示的是什么意思?谁依赖谁?
谁依赖谁? 最经典的:controll依赖于service ,service依赖于dao
依赖注入? 注入的是什么? 注入的是 对象 还有 普通的资源(字符串/boolean/int/float/double)
控制反转和依赖注入的核心功能包就是:Spring core模块完成的功能
4.使用Spring编写一个HelloWorld程序
1>: 编写程序的第一步:百度下载jar包 spring-framework-4.3.7.RELEASE-dist.jar
2>:在工程中导入这个包
commons-logging-1.1.3.jar --->依赖包 日志相关包,是用来辅助运行的
spring-beans-4.3.7.RELEASE.jar --->实体生成对象的包
spring-context-4.3.7.RELEASE.jar --->上下文相关包
spring-core-4.3.7.RELEASE.jar --->核心功能包
spring-expression-4.3.7.RELEASE.jar --->表达式相关的包
3>:在我们的src目录下 新建一个文件这个文件的名字是 ApplicationContext.xml这个文件(名字呢实际上是可以随便写)/bean.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:p="http://www.springframework.org/schema/p"
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 id="user_01" class="com.qf.helloword.User"></bean>
</beans>
4>:配置我们约束
在我们的下载包里面去找spring的配置文件 打开htmlsingle -->xmlns:p 找个长的 copy过来将bean中的所有的东西删除
5>:使用API获取这个对象
第一种模式
public void test() throws Exception {
//有两种模式来获取这个JAVA对象
//第一种 通过工厂模式来获取JAVA对象
//框架默认的路径就在src下
ClassPathResource resource=new ClassPathResource("bean.xml");
//获取这个工厂
XmlBeanFactory factory=new XmlBeanFactory(resource);
//第三步:获取这个JAVA对象
User user=(User) factory.getBean("user_01");
System.out.println(user);
}
第二种模式
public void test2() throws Exception {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
//第三步:获取这个JAVA对象
User user=(User) context.getBean("user_01");
System.out.println(user);
}
5.Spring的IOC/DI配置文件
现在这个对象默认是没有构造函数/没有说明到底是单例的与否....
1>:默认情况下 生成的JAVA对象是单例的
配置:
自动生成对象:
scope="prototype":这个就表示的是多例的
scope="singleton":这个表示的是单例的
lazy-init:表示的是是否延迟创建对象 ,这个只是对单例有效 ,如果不延迟创建那么在web工程中启动工程就会自动创建 ,如果延迟那么表示的是使用的时候才创建对象
destroy-method="destoryBobo":销毁方法
init-method="initBobo":初始化方法
<bean id="user_01" class="com.qf.helloword.User" scope="singleton" lazy-init="false" init-method="initBobo" destroy-method="destoryBobo"></bean>
假设我想给我们的对象赋值 怎么办?
调用有参数的构造器
<bean id="user_01" class="com.qf.helloword.User">
<!--这个表示调用的是有多个参数的构造器
index:表示的是参数的下标 value代表的是这个值-->
<!-- <constructor-arg index="0" value="中国"></constructor-arg>
<constructor-arg index="1" value="美国"></constructor-arg> -->
<!-- <constructor-arg name="userName" value="西瓜瓜"></constructor-arg>
<constructor-arg name="userPassword" value="123"></constructor-arg> -->
</bean>
下面引用字符串:
<!--假设我要在容器中放入 字符串的对象可不可以直接赋值呢?-->
<bean id="userName" class="java.lang.String">
<constructor-arg index="0" value="我是名字"></constructor-arg>
</bean>
<bean id="userPassword" class="java.lang.String">
<constructor-arg index="0" value="我是密码"></constructor-arg>
</bean>
<bean id="user_02" class="com.qf.helloword.User">
<constructor-arg index="0" ref="userName"></constructor-arg>
<constructor-arg index="1" ref="userPassword"></constructor-arg>
</bean>
工厂的模式来创建对象
<!--静态的方法生成我们的对象-->
<!--非静态的方法来生成对象-->
<bean id="factory" class="com.qf.helloword.UserFactory"></bean>
<!--省传入那个工厂里面指定方法的对象-->
<bean id="getNoStaticUser" factory-bean="factory" factory-method="getUserByNOStaticFacory"></bean>
<!--通过静态的方法来生成对象-->
<bean id="getStaticUser" class="com.qf.helloword.UserFactory" factory-method="getUserByStaticFacory"></bean>
接下来我们研究下获取对象的API
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
//第三步:获取这个JAVA对象
//如果使用了类型来找这个对象的话那么 在IOC容器里面就只能有一个类型的对象才能找到
//User user=(User) context.getBean(User.class);
//通过名字来找 最稳定的
// User user=(User) context.getBean("user_01");
//System.out.println(user);
注意:使用Spring的时候 默认调用的是无参数的构造参数
DI的配置
set 方法进行注入
1>:在需要对象的地方申明我们的类的成员变量
//Set注入的第一步:申明成员变量
private UserDao userDao=null;
//第二步:为成员变量生成set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//第三步:在我们的bean.xml中进行如下配置
<!--配置dao-->
<bean id="userDao" class="com.qf.di.UserDao"></bean>
<!--配置Service-->
<bean id="userService" class="com.qf.di.UserService">
<!--ref表示要引用我们ioc容器里面的资源-->
<property name="userDao" ref="userDao"></property>
</bean>
p标签进行注入
1>:在需要对象的地方申明我们的类的成员变量
//Set注入的第一步:申明成员变量
private UserDao userDao=null;
//第二步:为成员变量生成set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
<!--p标签注入-->
<bean id="userService" class="com.qf.di.UserService" p:userDao-ref="userDao"></bean>
内部bean的形式进行注入(基本不用)
<!--内部bean-->
<bean id="userService" class="com.qf.di.UserService">
<property name="userDao">
<bean class="com.qf.di.UserDao"></bean>
</property>
</bean>
自动装配
<!--自动装配-->
<bean id="userDao" class="com.qf.di.UserDao"></bean>
<!--name是通过名字找-->
<!-- <bean id="userService" class="com.qf.di.UserService" autowire="byName"></bean> -->
<!--通过类型找 那么在IOC的 容器中只能有一个对象 有多个的话那么会报错-->
<bean id="userService" class="com.qf.di.UserService" autowire="byType"></bean>
还可以设置全局的自动装配
注解模式的使用
1>:配置扫描器
<context:component-scan base-package="com.qf.anotation"></context:component-scan>
2>将对象放置到IOC容器呢?
@Component @Service @Repository
3>:注对象
@Resource @Autowired
注意: 在业务逻辑层推荐使用 @Service
在dao层推荐使用 @Repository
2017-09-13 01:25:06
6.注解的一些详解
1>.spring注解
@Component("user")
相当于配置文件里的 : <bean name="user" class="com.my.bean.User" /> -------把user对象放到容器中
以下三个注解和@Component("user")相同作用,只是为了体现是哪个层的对象
@Controller("user") // web层or控制层
@Service("user") // service层
@Repository("user")// dao层
例: -----User实体类
public class User {
private String name;
@Value("18") //注入值,还可以通过在setAge上面写这个注解来注入值
private Integer age;
@Autowired //自动装配,下面属性为对象,根据类型来检测容器当中所有符合这个属性类型的对象,所以在Car的实体类里要加上 @Component("car")把Car放入容器中
private Car car;//car实体类
注:如果匹配多个类型一致的对象.将无法选择具体注入哪一个对象.(即有多个car对象)
1).@Autowired //自动装配,
@Qualifier("car2")//使用Qualifier注解告诉spring容器自动装配哪个名称的对象
private Car car;
2).@Resource(name="car")//手动注入,指定注入哪个名称的对象
private Car car;
2>.其他注解
Service层
@Service -------默认情况下是将 UserSevice的对象放到 IOC容器里面去 ,默认的名字叫小写userService
@Service(value="userService") -----代表的是我们下面这个类放到IOC容器里面的时候的名字
@Scope(value="singleton")------设置这个类的生成模式 是单例的 还是多例的
@Lazy(value=false):--------这个表示的是是否默认延迟生成对象, 这个只是对单例有
@Repository:--将生成对象放到IOC的容器里面(用法一样)
@Component:--这个呢也是生成对象放到IOC容器里面(用法一样)
@Resource:---表示的是注入对象(必须在我们的IOC容器里面有这个对象才能进行注入)
这儿还未完,代码详解----************************************
7.AOP编程
1>. 什么是AOP编程?
AOP编程叫做面向切面的编程,------就是我们在开发中 ,可以将重复的代码抽取出来 形成一个类 ,当我们的程序在运行的时候通过代理的 方式,动态的将我们公共地方的代码可以植入进去进行运行, 这个思想 就叫做 面向切面的编程
抽取出来的这个公共的类我们以前要么叫基类 ,要么做成一个帮助类utils类;
而现在抽取出来的这个类 在面向切面编程中叫做 切面类!
代码被植入的地方称为切入点
描述代码植入的地点的表达式 就称为 切入点表达式
2>. AOP面向切面编程思想:
过滤器,拦截器,动态代理 都可以体现AOP思想
spring aop开发:
spring封装了动态代理代码,通过配置的形式,我们就不需要手写动态代理代码(被代理对象必须实现接口),还封装了cglib代理 (不需要接口),所以封装了这两个类就可以对任何类进行代理增强。
3>. AOP切入点表达式:
com.my.service.UserServiceImpl.save() // 返回值任意类型,匹配得是com.my.service包下的UserServiceImpl类的空参save方法
com.my.service.UserServiceImpl.*() // *() 所有空参方法
com.my.service.*ServiceImpl.*(..) // *ServiceImpl.*(..)表示匹配所有以ServiceImpl结尾的类并且参数不要求的所有方法
com.my.service..*ServiceImpl.*(..) // 两点表示service包的子包也考虑在内
4>.传统的AOP
1 @Service//注解,告诉我们属于业务层 2 public class UserService { 3 @Autowired //自动装配 4 private Aop aop=null; 5 6 @Autowired 7 private UserDao userDao=null; 8 9 public void regsiter(){ 10 aop.startTransaction(); 11 userDao.save(); 12 aop.endTransaction(); 13 } 14 }
5>.cglib下实现代理
1 @Component 2 public class UserServiceProxy implements MethodInterceptor{ 3 @Autowired 4 private UserService userService=null; 5 @Autowired 6 private Aop aop=null; 7 8 /** 9 * 生成对象 10 * @return 11 */ 12 public Object getObject(){ 13 Enhancer enhancer=new Enhancer(); 14 enhancer.setSuperclass(userService.getClass()); 15 enhancer.setCallback(this); 16 return enhancer.create(); 17 } 18 @Override 19 public Object intercept(Object object, Method method, Object[] args, 20 MethodProxy arg3) throws Throwable { 21 //首先获取的是方法体的名字 22 String methodName=method.getName(); 23 Object returnValue=null; 24 25 if("regsiter".equals(methodName)){ //表示当前执行的是regsiter方法 26 aop.startTransaction(); 27 //执行这个方法 28 returnValue=method.invoke(userService,args); 29 //植入我们的关闭事务的方法 30 aop.endTransaction(); 31 }else{ 32 33 returnValue=method.invoke(userService, args); 34 } 35 return returnValue; 36 } 37 38 }
6>.动态实现AOP编程
1 @Test 2 public void test() throws Exception { 3 //生成一个动态代理的对象出来 4 ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/qf/aop_03/bean.xml"); 5 final Aop aop=context.getBean(Aop.class); 6 final UserService service=context.getBean(UserService.class); 7 8 IUserService service2=(IUserService) Proxy.newProxyInstance( 9 UserService.class.getClassLoader(), 10 UserService.class.getInterfaces(), 11 new InvocationHandler() { 12 /** 13 * 方法执行的时候的中断的方法 14 */ 15 @Override 16 public Object invoke(Object proxy, Method method, Object[] args) 17 throws Throwable { 18 //获取请求方法的名字 19 String methodName=method.getName(); 20 Object returnValue=null; 21 if("regsiter".equals(methodName)){ 22 //说明目前访问的是register方法 23 aop.startTransaction(); 24 returnValue=method.invoke(service, args); 25 aop.endTransaction(); 26 }else{ 27 returnValue=method.invoke(service, args); 28 } 29 30 return returnValue; 31 } 32 }); 33 34 service2.regsiter(); 35 }
7>.注解下的AOP
@Component //这个表示的是当前这个类放到我们的ioc容器中去
@Scope("singleton") //当前这个类生成对象的时候 使用的单例
@Aspect //表示当前的这个类是一个切面类
例:
就需要告诉Spring 我们要将程序放到哪里去
(execution ( : 表示的是语法规则
* : 表示的是返回值类型可以是任意的类型
com.my.aop.anotation.UserService.* : 后面的这个*表示的是所有的方法
(..) : 这个表示的是参数的数据类型
完整组合起来就是:execution ( * com.qf.aop.anotation.UserService.* (..) )
切入点表达式
@Pointcut(value="(execution (* com.qf.aop.anotation.UserService.*(..)))")
public void pt(){
}
@Before("pt()"):表示的是在执行切入点方法之前调用下面的方法
@After("pt()"):表示的是执行切入点表达式方法之后要执行的方法
@AfterThrowing("pt()"):出现异常的时候执行的方法
@AfterReturning("pt()"):返回值的时候动态植入的方法
@Around("pt()"):环绕的时候执行的方法
8>.配置模式下的AOP
1 <beans xmlns="http://www.springframework.org/schema/beans"
2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
3 xmlns:context="http://www.springframework.org/schema/context"
4 xmlns:aop="http://www.springframework.org/schema/aop"
5 xsi:schemaLocation="
6 http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans.xsd
8 http://www.springframework.org/schema/context
9 http://www.springframework.org/schema/context/spring-context.xsd
10 http://www.springframework.org/schema/aop
11 http://www.springframework.org/schema/aop/spring-aop.xsd">
12 <!--配置dao-->
13 <bean id="userDao" class="com.qf.aop.config.UserDao"></bean>
14
15 <!--配置咋们的Service-->
16 <bean id="userService" class="com.qf.aop.config.UserService" p:userDao-ref="userDao"></bean>
17
18 <!--配置我们的aop对象-->
19 <bean id="aop" class="com.qf.aop.config.Aop"></bean>
20
21 <!--下面就开始配置我们的aop了-->
22 <aop:config>
23 <!--配置的是切入点表达式-->
24
25
26 <aop:pointcut expression="(execution (* com.qf.aop.config.UserService.*(..)))" id="pt"/>
27 <aop:aspect ref="aop">
28 <!--环绕的时候执行-->
29 <aop:around method="returnAround" pointcut-ref="pt"/>
30 <!--在执行某一个方法之前来执行-->
31 <aop:before method="startTransaction" pointcut-ref="pt"/>
32 <!--在某个方法之后植入指定代码-->
33 <aop:after method="endTransaction" pointcut-ref="pt"/>
34 <!--出现异常-->
35 <aop:after-throwing method="throwException" pointcut-ref="pt"/>
36 <!--返回结果的时候植入代码-->
37 <aop:after-returning method="returnAfter" pointcut-ref="pt"/>
38 </aop:aspect>
39 </aop:config>
40 </beans>
8.Spring提供的JdbcTemplate来实现数据库的相关操作
1.Spring中配置我们的C3p0连接池
1>:要使用Spring提供的 Jdbctemplate来完成数据库操作的话 首先导入包
Spring对Jdbctemplate支持的包
spring-jdbc-4.3.7.RELEASE.jar jdbc支持包
spring-tx-4.3.7.RELEASE.jar 事务相关的包
c3p0-0.9.1.2.jar C3p0连接池的相关包
mysql-connector-java-5.1.7-bin.jar 驱动程序的相关包
2>:在配置文件中进行如下的配置
1 <!--要使用C3p0的话首先配置数据源-->
2 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
3 <property name="acquireIncrement" value="2"></property>
4 <property name="maxPoolSize" value="100"></property>
5 <property name="initialPoolSize" value="2"></property>
6 <property name="minPoolSize" value="2"></property>
7 <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
8 <property name="jdbcUrl" value="jdbc:mysql:///Day1704_Spring"></property>
9 <property name="user" value="root"></property>
10 <property name="password" value="root"></property>
11 </bean>
12
13 <!--配置我们的Spring中核心的访问数据库的这个类-->
14 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
15 <property name="dataSource" ref="dataSource"></property>
16 </bean>
17
18 <!--配置我们的userDao对象-->
19 <bean id="userDao" class="com.qf.jdbc.UserDao" p:jdbcTemplate-ref="jdbcTemplate"></bean>
3>:编写增删该查的方法
1 public class UserDao {
2
3
4 private JdbcTemplate jdbcTemplate=null; //这个类是Spring提供的访问数据库的
5 public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
6 this.jdbcTemplate = jdbcTemplate;
7 }
8 /**
9 * 添加数据
10 * @param user
11 */
12 public void save(String uName,String uPassword){
13 String sql="insert into t_user(uName,upassword) values(?,?)";
14 jdbcTemplate.update(sql,uName,uPassword);
15 }
16 /**
17 * 删除数据
18 * @param user
19 */
20 public void delete(int uId){
21 String sql="delete from t_user where uId=?";
22 jdbcTemplate.update(sql,uId);
23 }
24 /**
25 * 更新数据
26 * @param user
27 */
28 public void update(User user){
29 String sql="update t_user set uName=?,uPassword=? where uId=?";
30 jdbcTemplate.update(sql,user.getuName(),user.getuPassword(),user.getuId());
31 }
32 /**
33 * 查询数据
34 * @param user
35 */
36 public List<User> query(){
37 String sql="select * from t_user";
38 List<User> list=jdbcTemplate.query(sql,new RowMapper<User>(){
39 @Override
40 public User mapRow(ResultSet set, int arg1) throws SQLException {
41
42 int uId=set.getInt("uId");
43 String uName=set.getString("uName");
44 String uPassword=set.getString("uPassword");
45 User user=new User();
46 user.setuId(uId);
47 user.setuName(uName);
48 user.setuPassword(uPassword);
49 return user;
50 }
51 });
52
53 return list;
54 }