上图是整理的Spring框架中常用的知识点.
Spring是什么吗?
Spring是一种框架型的框架.可以整合其他框架一起使用.
Spring是J2EE应用程序框架,是轻量级IOC和AOP的肉国企框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Stryts框架,ibatis框架等组合使用。
(1)IOC(Inversion of Control)控制反转,对象创建责任的反转,在spring中BeanFactory是IOC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。XMLBeanFacotory实现BeanFactory接口,通过获取xml配置文件数据,组成应用对象及对象间的依赖关系。
spring中有三种注入方法,一种是set注入,一种是接口注入,另一种是构造方法注入
(2)AOP面向切面编程
aop就是纵向的编程。比如,业务1和业务2都需要一个共同的操作,与其往每个业务中都添加同样的代码,不如写一遍代码,让两个业务共同使用这段代码。
spring中面向切面编程的实现有两种方式,一种是动态代理,一种是CGLIB,动态代理必须要提供接口,而CGLIB实现是有继承。
为什么用它?
1.开发方便,代码量少.
2.代替了new对象,节省内存空间.
3.它可以整合其他框架.
Spring最核心的思想:
Spring最核心的功能:管理对象()
管理对象的生命周期,和对象之间的关系。
1.IOC控制反转:通过依赖注入来实现的把原来的自己new对象, 现在交给Spring容器。
DI依赖注入:注解 反射
2.AOP面向切面编程
3.与JDBC,DataSource hibernate s2sh整合
概念:JavBean(实体类)必须遵循一个规则(没有用Spring框架写实体类的方法):
1.必须有包
2.必须有无参构造器
3.实现序列化接口
4.有get()和set()方法
5.toString()
如果用Spring容器来做,以上步骤只保留第一步就行了,其他都可以省略。
Spring搭建流程:
1.导包 (必须的2个)
2.在src目录下创建applicationContext.xml(框架的核心配置文件)
3.约束文件
4.将实体类添加到Spring容器里
Spring框架的优缺点:
优点:
* 轻量级的容器框架,没有侵入性。
* IOC更加容易组合对象之间的关系,通过面向接口进行编程,可以低耦合开发。
* 易于本地测试(Junit单元测试,不用部署服务器)
* AOP可以更加容易的进行功能扩展,遵循ocp开发原则
* Spring默认对象的创建为单例的,我们不需要在使用单例的设计模式开开发单体类。
* Spring的集成很强大,另外可以对其他框架的配置进行一元化管理。
* Spring的声明式事物的方便使用。
缺点:
* 开发对设计要求较高,集成测试麻烦,对框架有一定的依赖性。
Spring创建对象的时间:
默认执行步骤:(lazy-init=false)
1.默认无参构造器
2.初始化一个Spring容器
3.提取bean
4.调用方法并打印
提取几次bean?
2.提取 2次打印
懒加载?((lazy-init=true )
1.初始化Spring容器
2.提取bean
3.默认构造器
4.调方法并打印
总结:同时提取2个bean 一个bean提取2次,一个bean提取一次
如果配置文件中,一个bean加入lazy-init=true,那么它会把执行权交给下一个提取的对象。
两个bean的执行步骤:
1.初始化Spring容器
2.Hello中的默认无参构造器
3.Hello2中的默认无参构造器
4.提取hello的bean
5.提取hello2的bean
6.调用Hello的say();
7.调用hello2的say()
两个bean中提取多次,执行顺序:(默认单例模式)
1.初始化Spring容器
2.单例模式:Hello2,构造器执行
3.元型模式:hello构造器执行
4.提取一次bean 打印一次(前提是在元型模式下执行)
5.调用方法 按照顺序依次执行.
两个bean Hello提取多次 单例模式,不是懒加载
Hello2 提取一次 元型模式 是懒加载
执行顺序:
1.初始化Spring容器
2.单例模式的构造器执行
3.提取单例的bean
4.元型模式hello2,构造器执行
5.依次执行
总结:作用域
如果指定scope=“singleton”单例模式 构造器只执行一次
如果指定scope=“prototype”提取几次bean,构造器就执行几次
- scope="singleton" 单例模式,lazy_init=false 什么时候 创建对象?
单例对象,在实例化 spring 容器时 - scope="prototype" lazy-init="false"多例模式什么时 候创建对象?
多例,在提取 bean 时候 - scope="singleton" 单例模式,lazy_init=false 什么时候 创建对象?
在第一次提取 bean 时候创建对象,只创建一次,再次提取不会重复创建 - scope="singleton" 单例模式,lazy_init=true 什么时候 创建对象?
每次提取 bean 时候,创建对象
执行顺序和配置文件中的bean有关系:bean靠上位置,优先执行构造器
Spring中的bean对象是否是单例模式?
是,不管提取几次同一个bean,都只会执行一个构造器
注册时写两个属性
init-method="init" destroy-method="destory"
DI依赖注入:给参数赋值的过程就叫注入
(1)setter注入
//实体类student的属性,一定要有set()和get方法
private Integer id;
private String name;
private Classes cls;
private List list;
private Set set;
private Map map;
//实体类classes中什么也没写
<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 definitions here xmlns:xmlnamespace xml文件命名空间 -->
<!--注册hello对象注册到Spring容器(appcationContext) 注册进来后变成每个唯一bean标签 id 是指该bean的唯一实例
class是全类型 --><!--scope作用范围:prototype元型模式 singleton单例模式 bean默认是单例模式 -->
<bean id="cls" class="cn.lanou3g.entity.Classes"/>
<bean id="stu" class="cn.lanou3g.entity.Student">
<!-- 普通类型的注入 所有的子标签都是父标签的属性 -->
<property name="id" value="1037227" />
<property name="name" value="nana"></property>
<!-- 当出现类类型的时候要有ref -->
<property name="cls" ref="cls" />
<!-- 常用集合类的注入 -->
<property name="list">
<!--list集合 -->
<list >
<value>大学英语</value>
<value>数据结构</value>
<value>高数</value>
</list>
</property>
<!-- set集合 -->
<property name="set">
<set>
<value>大学英语1</value>
<value>数据结构1</value>
<value>高数1</value>
</set>
</property>
<property name="map">
<map>
<entry value="1001" key="01"/>
<!-- <key>
<value>大学英语1</value>
</key>
</entry> -->
<entry value="1002" key="02"/>
<!--< key>
<value>大学英语2</value>
</key>
</entry> -->
</map>
</property>
</bean>
</beans>
//测试
@Test
public void testConn(){
//初始化Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//提起bean,根据容器中的id来获取的
Student stu=(Student)ctx.getBean("stu");
//调方法
stu.method();
}
(2)构造函数的注入方法
实体类和上面setter注入的一样,只多加一会有参的构造函数
在主配置文件中不同,这是通过下标赋值的
<bean id="cls" class="cn.lanou3g.entity.Classes"/>
<bean id="stu" class="cn.lanou3g.entity.Student">
<constructor-arg index="0" value="1001"/>
<constructor-arg index="1" value="lida"/>
<constructor-arg index="2" ref="cls"/>
</bean>
还有一种方法是通过数据类型赋值的 实体类还和上面一样
主配置不用
<bean id="cls" class="cn.lanou3g.entity.Classes"/>
<bean id="stu" class="cn.lanou3g.entity.Student">
<constructor-arg type="java.lang.Integer" value="1001"/>
<constructor-arg type="java.lang.String" value="lida"/>
<constructor-arg type="cn.lanou3g.entity.Classes"/>
</bean>
Spring创建对象的方式
1.无参构造器(默认)
2.工厂模式
静态工厂的创建方式:
创建一个工厂
自定义一个静态方法(被static修饰)
测试的时候直接.
//静态工厂
public class StaticFactory {
public static Hello getHello(){
return new Hello();
}
}
//测试
@Test
public void testConn(){
Hello hello=StaticFactory.getHello();
hello.say();
}
实例工厂创建方式:
创建一个工厂
自定义方法
测试时需要从new
//实例工厂
public class InstanceFactory {
public Hello getHello(){
return new Hello();
}
}
//测试
@Test
public void testCon(){
InstanceFactory ins = new InstanceFactory();
Hello hello=ins.getHello();
hello.say();
}
AOP通知
- 前置通知
- 后置通知
- 异常通知
- 最终通知
- 环绕通知:可以做权限 可以代替前后通知
/开启第一个切面 5中通知
public class SessionAspect {
//前置通知
public void before(JoinPoint join){
System.out.println("前置通知");
}
//后置通知
public void after_returning(JoinPoint join){
System.out.println("后置通知");
}
//最终通知
public void after(JoinPoint join){
System.out.println("最终通知");
}
//异常通知
public void after_throwing(JoinPoint join,Throwable ex){
System.out.println("异常通知");
}
//环绕通知
public void around(ProceedingJoinPoint point){
System.out.println("环绕通知1");
try {
//用连接点调进程
point.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("环绕通知2");
}
}
<?xml version="1.0" encoding="UTF-8"?>
-<beans xsi:schemaLocation="
[http://www.springframework.org/schema/beans](http://www.springframework.org/schema/beans)[http://www.springframework.org/schema/beans/spring-beans.xsd](http://www.springframework.org/schema/beans/spring-beans.xsd)[http://www.springframework.org/schema/aop](http://www.springframework.org/schema/aop)[http://www.springframework.org/schema/aop/spring-aop.xsd"](http://www.springframework.org/schema/aop/spring-aop.xsd%22);
xmlns:aop="[http://www.springframework.org/schema/aop"];
xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance"];
xmlns="[http://www.springframework.org/schema/beans">];
<!-- bean definitions here -->
<bean class="cn.lanou3g.aspect.SessionAspect" id="sessionAspect"/>
<bean class="cn.lanou3g.aspect.TransactionAspect" id="transactionAspect"/>
<bean class="cn.lanou3g.entity.TargetObject" id="target"/>
-<aop:config>
<aop:pointcut id="p" expression="execution(* cn.lanou3g.entity.*.*(..))"/>
-<aop:aspect ref="sessionAspect">
<!-- 前置 -->
<!-- <aop:before method="before" pointcut-ref="p"/> -->
<!-- 后置-->
<!-- <aop:after-returning method="after_returning" pointcut-ref="p"/> -->
<!-- 最终 -->
<!-- <aop:after method="after" pointcut-ref="p"/> -->
<!-- 异常 -->
<!-- <aop:after-throwing method="after_throwing" throwing="ex" pointcut-ref=" p"/> -->
<!-- 环绕 -->
<aop:around pointcut-ref="p" method="around"/>
</aop:aspect>
</aop:config>
</beans>
测试结果
前置通知
环绕通知1
session.save
后置通知
最终通知
环绕通知2
总结:
1.前置通知和最终通知与目标方法是否执行没有直接关系;
2.后置通知必须在目标方法执行之后执行,如果目标方法没有正常结束,后置通知不执 行;
3.异常通知:目标方法出异常的时候执行,捕捉异常
4.环绕通知: 可以控制目标方法的执行(执行顺序是在目标方法之前和之后;
整合Spring-jdbc
1.导包(25个)
2.连接数据库(jdbc.properties)
3.实体类
4.Spring配置文件(application.xml)
5.三层 dao service controller
6.注入到Spring容器中
7.测试
.Spring中有那些主要模块:Dao ORM JEE Wed Aop IOC
Spring中用到的设计模式: 代理 单例模式 原型模式 工厂模式
Spring中事务该如何配置:
(1)配置工厂,产生session
(2)开启session和事务,这里可以自动开启
(3)进行动态代理
(4)配置切面及通知
(5)设置切入点,执行通知
(6)自动提交事务
Spring框架注解按分层分几种:
@Component 在类上面写
@Controller 控制层,就是我们的action层.
@Service 业务逻辑层 就是我们的Service或者manager层
@Repository 注入的时候写