一.IoC
- 中文名:控制反转
- 英文名:Inversion of control
- 什么是IoC?
从字面意思开始理解: 控制和反转
控制:Spring把控制对象实例的任务,交给了Spring的容器,不仅如此,这个容器还控制着对象的声明周期,存储什么对象
反转:首先理解原来的常规流程(正向),由原有对象自主创建一个新的对象的过程,即直接使用new方法创建一个对象出来.
现在这件事,一律交给大哥来解决——>IoC容器,它现在帮我们管理这件事.
简述:原始的直接使用new的方式创建对象,会使得整个项目代码耦合度太高,不利于维护.(看图)
所以我们使用IoC容器的最大作用就是帮助我们解耦各个对象之间的联系.
举例:
Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。
采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定
总结:IoC(控制反转)
从文件资源中读取相关配置文件,然后将这些配置注入到对象中,
本来是类直接控制其他类的创建,这是正向的,但是我现在把这件事交给Spring(来帮助我们创建实例化对象,同时,他也负责读取文件资源)让外部类控制创建这个类,就是控制反转
IoC容器帮助我们从外部取出资源(xml文件中<bean>的配置...),这些资源(xml文件)记录着我们配置文件,他们是某个对象创建所需的,因此,我们需要把它给注入到它需要的类中,来创建对象.(这种解释也叫依赖注入(DI(Dependcy Injection)))
作用:解耦.
二.Spring环境搭建
- 导入jar包
- 配置xml文件
- 编写测试类
详细过程:
1.导jar
从上到下,依次
1.1 logging 日志包
1.2 Core Container(编写Spring测试,所需最少的包)
a) Beans Spring负责创建类对象并管理对象b) Core 核心类
c) Context 获取上下文参数或者获取外部资源 d) SpEl: expression.jar,Spring表达式语言(Spring Expression Language )
现在只用到了Core Container
2.src下新建applicationContext.xml
① xml文件名称和路径自定义,我自己为了方便,放在src下.
这个xml是外部资源,是对象的依赖,配置信息会被IoC容器-->ApplicationContext读取
②开始配置xml.
a) 配置基本 schema
Spring配置文件基于schema
schema理解:DTD升级版,拥有更好的扩展性,可以整合很多其他的东西(hibernate等)
schema 文件扩展名.xsd,每次引入一个 xsd 文件是一个 namespace(xmlns)
b) 配置<bean/>
配置<bean/>配置类,之后xml文件被加载,对象就会被创建出来
c) 编写测试类
getBean()获得对应id的对象,(第二个参数不传默认Object)
getBeanDefinitionNames()或的容器中所有对象
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- id 表示获取到对象标识
class 创建哪个类的对象
-->
<bean id="stu" class="com.sshqx.pojo.Student"/>
</beans>
实体类
package com.sshqx.pojo;
public class Student {
private int id;
private int tid;
private String sname;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTid() {
return tid;
}
public void setTid(int tid) {
this.tid = tid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", tid=" + tid + ", sname=" + sname + ", age=" + age + "]";
}
}
测试
package com.sshqx.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sshqx.pojo.Student;
public class test01 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu = ac.getBean("stu", Student.class);
System.out.println(stu);
// 获取所有的Spring容器中目前所有管理的所有对象 id
// String[] names = ac.getBeanDefinitionNames();
// for (String string : names) {
// System.out.println(string);
// }
}
}
三.spring创建对象的三种方式
1.构造器
a) 默认无参构造,无需其他配置
b)若使用有参构造,需要额外配置
b1) 实体类添加有参构造方法
b2) xml<bean>中使用<constructor-arg>
<bean id="stu" class="com.sshqx.pojo.Student">
<constructor-arg index="0" name="id" type="int" value="111"></constructor-arg>
<constructor-arg index="1" name="tid" type="int" value="222"></constructor-arg>
<constructor-arg index="2" name="sname" type="String" value="小红"></constructor-arg>
<constructor-arg index="3" name="age" type="int" value="18"></constructor-arg>
</bean>
参数详解:
<bean> id:对象的引用,class创建什么类对象
<constructor-arg> index有参构造器中参数按照索引排序, name:实体类中属性的名称,
type实体类中属性声明的类型val:值等于多少ref:引用另一个<bean>(意思就是ref引用一个创建出来的对象)
2.实例工厂
a)创造工厂
b)配置xml实例化对象
c)测试
工厂类
package com.sshqx.pojo;
public class StudentFactory {
public Student newInstance(){
return new Student(1,2,"小刚",18);
}
}
配置xml
<bean id="factory" class="com.sshqx.pojo.StudentFactory"></bean>
<bean id="stu1" class="com.sshqx.pojo.Student" factory-bean="factory"
factory-method="newInstance"></bean>
配置测试
Student stu1 = ac.getBean("stu1",Student.class);
System.out.println(stu1);
测试结果
3.静态工厂
a) 与2大致相同,修改Factory类中的方法为静态方法;
b) 编写xml<bean>
<bean id="stu1" class="com.sshqx.pojo.StudentFactory" factory-method="newInstance"></bean>
结果同2
四.如何给Bean的属性赋值(注入)
1.构造方法设置
2.通过set方法注入
2.1 属性是基本类型和String
<bean id="stu1" class="com.sshqx.pojo.Student">
<property name="id" value="1"></property>
<property name="tid" value="2"></property>
<property name="sname" value="小刚"></property>
<property name="age" value="4"></property>
</bean>
等价于
<bean id="stu2" class="com.sshqx.pojo.Student">
<property name="id">
<value>1</value>
</property>
<property name="tid">
<value>3</value>
</property>
<property name="sname">
<value>小红</value>
</property>
<property name="age">
<value>18</value>
</property>
</bean>
2.2如果属性是set<?>
<property name="sets">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</set>
</property>
2.3如果属性是 List<?>
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
如果list中只有一个属性也可以这么写
<property name="list" value="1"></property>
2.4如果属性是数组,属性只有一个方法同上
<property name="strs" >
<array>
<value>1</value>
<value>2</value>
<value>3</value>
</array>
</property>
2.5如果属性是map
<property name="map">
<map>
<entry key="a" value="b" >
</entry>
<entry key="c" value="d" >
</entry>
</map>
</property>
2.6如果属性是properties
<property name="demo">
<props>
<prop key="key">value</prop>
<prop key="key1">value1</prop>
</props>
</property>
六.DI
1.代码体现
把一个类注入另一个类
<bean id="peo" class="com.bjsxt.pojo.People">
<property name="desk" ref="desk"></property>
</bean>
<bean id="desk" class="com.bjsxt.pojo.Desk">
<property name="id" value="1"></property>
<property name="price" value="12"></property>
</bean>
七.MyBatis和Spring的简单整合
首先了解一下流程:
TomCat启动之后会自动加载web.xml---->读取到监听器(帮助Spring加载监听文件)---->去读取资源文件(applicationContext.xml)---->曾经在mapper.xml中配置的东西现在几乎全用apllicatiomContext.xml取代(理解原理:使用Spring的IoC容器帮助我们创建对象,解耦过程,简单的说就是把创建对象的过程给抽离出来,service等层只负责接收创建出来的对象,IoC和DI)---->配置applicationContext.xml(这里不细说,前面说过了该怎么配置,这里就是应用)---->使用:先获取webApplicationContext(这里有创建好的对象)执行操作
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- Spring配置文件 -->
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<!-- 监听器帮助加载Spring配置文件 -->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 数据源封装类,数据源:获取数据库连接 -->
<bean id="dataSouce" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 创建SqlSessionFactory对象 -->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据连接信息来源于dataSource -->
<property name="dataSource" ref="dataSouce"></property>
</bean>
<!-- 配置扫描器,相当于mybatis.xml下的package,会扫描mapper包后,给接口创建对象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 需要扫描的包 -->
<property name="basePackage" value="com.sshqx.mapper"></property>
<!-- 和哪个工厂产生关系 -->
<property name="SqlSessionFactory" ref="factory"></property>
</bean>
<!-- 通过设置注入,给studentMapper赋值 -->
<bean name="studentService" class="com.sshqx.service.impl.StudentServiceImpl">
<property name="studentMapper" ref="studentMapper"></property>
</bean>
</beans>
servlet导包我就不写了
@WebServlet("/show")
public class StudentServlet extends HttpServlet{
private StudentService studentService;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
WebApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
List<Student> list = ac.getBean("studentService",StudentServiceImpl.class).show();
req.setAttribute("list", list);
req.getRequestDispatcher("index.jsp").forward(req, resp);
return;
}
}
service
package com.sshqx.service;
import java.util.List;
import com.sshqx.pojo.Student;
public interface StudentService {
List<Student> show();
}
serviceImpl
public class StudentServiceImpl implements StudentService{
private StudentMapper studentMapper;
@Override
public List<Student> show() {
return studentMapper.selAll();
}
public StudentMapper getStudentMapper() {
return studentMapper;
}
public void setStudentMapper(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
}
Student实体类
package com.sshqx.pojo;
public class Student {
private int id;
private int tid;
private String sname;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTid() {
return tid;
}
public void setTid(int tid) {
this.tid = tid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", tid=" + tid + ", sname=" + sname + ", age=" + age + "]";
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int id, int tid, String sname, int age) {
super();
this.id = id;
this.tid = tid;
this.sname = sname;
this.age = age;
}
}
Studentmapper
package com.sshqx.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import com.sshqx.pojo.Student;
public interface StudentMapper {
@Select("select * from student")
List<Student> selAll();
}
第二天
一.AOP
中文名称:面向切面编程
英文名称:(Aspect Orented Programing)
什么是AOP?
解释:在原有的纵向流程代码中添加横切面.(在原有代码的基础上,在某一方法或者某些方法添加前置,后置通知等操作,形成横切面)
为什么使用AOP(添加前置通知,后置通知...)?
解释:使得原有程序的职责更明确.把原有代码的经常重复的逻辑代码提取出来
画图理解:
实现原:(单个方法)
实现原理:(多个方法,过程2的箭头画反了.)
优点:和为什么使用差不多,在不修改原代码基础上,实现了原有程序的扩展,脱离出了部分重复逻辑代码原有代码职责更加明确
常用概念:
pointcut:等待扩展的方法扩展前就是pointcut(切点)
before advice:前置通知
after advice:后置通知
throws advice:异常通知
整合了以上任意一个或者多个功能就是切面
Spring的AOP实现方式
1.Schema-based
特点:通知全需要实现接口,配置Spring配置文件<aop:config>
2.Aspectj
特点:通知不需要实现接口或者类,配置Spring配置文件<aop:config>字标签<aop:aspect>
①Schema-based具体实现
1..导入jar包
2.声明前置,后置通知
前置实现xx接口,后置实现xx接口(注意实现,看代码)
前置:
public class BeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("我是开始代理,我先吃,哈哈");
}
}
后置:
public class AfterAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
System.out.println("我是结束代理,最后吃,啊,好惨");
}
}
需要注意:参数
前置:(arg0,arg1,atg2)
切点方法对象,切点参数,切点方法的类对象
后置:(arg0,arg1,atg2,arg3)
返回值对象,方法对象,切点参数.切点返回类对象
3.修改applicationContext.xml配置
首先引入AOP命名空间(xsd)
1.配置通知类
id随便起class对应自己声明的通知类
<!-- 配置通知类对象 -->
<bean id="mybefore" class="com.sshqx.advice.BeforeAdvice"></bean>
<bean id="myafter" class="com.sshqx.advice.AfterAdvice"></bean>
2.配置<aop:config>
expression:固定表达式,其中".."代表可变参数;包名类名等,可以用"*"替换
advice-ref与1中id相同
pointcut-ref与<aop:pointcut>中id相同
<!-- 配置需要的切点和完成通知映射 -->
<aop:config >
<aop:pointcut expression="execution(* com.sshqx.demo.Demo01.*(..))" id="demo"/>
<aop:advisor advice-ref="mybefore" pointcut-ref="demo"/>
<aop:advisor advice-ref="myafter" pointcut-ref="demo"/>
</aop:config>
3.配置测试类
<bean id="test" class="com.sshqx.demo.Demo01"></bean>
4.编写测试代码
public class Test01 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Demo01 demo01 = ac.getBean("test",Demo01.class);
demo01.demo01("hehe ", 18);
demo01.demo02();
}
}
5.测试结果
②.Aspectj方式(以异常通知为例)
1.导入jar
同①(两个方式的都导入了)
2.声明通知类class(不需要继承接口),所有的通知都可以写入其中
MyAdvice.class
public class MyAdvice {
public void myThrowsAdvice(Exception e){
System.out.println("错错错!"+e.getMessage());
}
public void myAfter(){
System.out.println("后后后");
}
public void myBefore(){
System.out.println("前前前");
}
}
3.修改xml文件
添加xsd 同①
构建通知类<bean>
<bean id="advice" class="com.sshqx.advice.myAdvice"></bean>
修改<aop:config>下的<aop:aspect>
在 spring 配置文件中配置
<aop:aspect>的 ref 属性表示:方法在哪个类中.
<aop: xxxx/> 表示什么通知
method: 当触发这个通知时,调用哪个方法
throwing: 异常对象名,必须和通知中方法参数名相同(可以不在通知中声明异常对象)
<aop:config>
<aop:aspect ref="advice">
<aop:pointcut expression="execution(* com.sshqx.demo.Demo01.*())" id="mypoint"/>
<aop:before method="myBefore" pointcut-ref="mypoint"/>
<aop:after-throwing method="myThrowsAdvice" pointcut-ref="mypoint" throwing="e"/>
<aop:after method="myAfter" pointcut-ref="mypoint"/>
</aop:aspect>
</aop:config>
创建测试类<bean>
<bean id="test" class="com.sshqx.demo.Demo01"></bean>
4.写测试类
public class Test01 {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Demo01 demo01 = ac.getBean("test",Demo01.class);
demo01.demo02();
}
}
5.输出测试结果
未出错
出错
③.使用Schema-based方式配置
与前面配置before after大体一致
注意:
实现throwsAdvice 接口
自己创建afterThrowing方法,名字不可变动
异常类型与报错类型一致,
方法参数 一个或者四个
异常通知类的写法
public class MyThrowsAdvice implements ThrowsAdvice{
// public void afterThrowing(Method m, Object[] args,Object target, Exception ex) {
// System.out.println("执行异常通知");
// }
public void afterThrowing(Exception ex){
System.out.println("执行异常通知"+ex.getMessage());
}
}
其余几乎一致
④环绕通知:使用(Schema-based 方式)
修改两个配置即可
1.构建环绕通知类实现xxxx接口
注意arg0.proceed
public class MyInterceptor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("倩倩倩倩");
//放行,调用切点
arg0.proceed();
System.out.println("吼吼吼吼");
return null;
}
}
2.修改xml
<bean id="myInterceptor" class="com.sshqx.advice.MyInterceptor"></bean>
<aop:advisor advice-ref="myInterceptor" pointcut-ref="mypoint"/>
⑤.环绕通知Aspectj方式
注意声明方式参数
public void myArround(ProceedingJoinPoint p) throws Throwable{
System.out.println("前前前--环绕");
p.proceed();
System.out.println("后后后--环绕");
}
若有参数(一个方法就是;一个pointcut比较烦) arg-names要传递参数名必须一样
<aop:pointcut expression="execution(* com.sshqx.test.Demo.demo1(String,int)) and args(name1,age1)" id="mypoint"/>
<aop:pointcut expression="execution(* com.sshqx.test.Demo.demo1(String)) and args(name1)"
id="mypoint1"/>
<aop:before method="mybefore" pointcut-ref="mypoint" arg-names="name1,age1"/>
<aop:before method="mybefore1" pointcut-ref="mypoint1" arg-names="name1"/>
六.基于aspectj使用注解
也挺麻烦的,我就不试验了,拷贝一段解释
1. spring 不会自动去寻找注解,必须告诉 spring 哪些包下的类中可能
有注解
1.1 引入 xmlns:context
<context:component-scan
base-package="com.bjsxt.advice"></context:component-s
can>
2. @Component
2.1 相当于<bean/>
2.2 如果没有参数,把类名首字母变小写,相当于<bean id=””/>
2.3 @Component(“自定义名称”)
3. 实现步骤:
3.1 在 spring 配置文件中设置注解在哪些包中
<context:component-scan
base-package="com.bjsxt.advice,com.bjsxt.test"></cont
ext:component-scan>
3.2 在 Demo 类中添加@Componet
3.2.1 在方法上添加@Pointcut(“”) 定义切点
@Component
public class Demo {
@Pointcut("execution(*
com.bjsxt.test.Demo.demo1())")
public void demo1() throws Exception{
// int i = 5/0;
System.out.println("demo1");
}
}
3.3 在通知类中配置
3.3.1 @Component 类被 spring 管理
3.3.2 @Aspect 相当于<aop:aspect/>表示通知方法在当前类中
@Component
@Aspect
public class MyAdvice {
@Before("com.bjsxt.test.Demo.demo1()")
public void mybefore(){
System.out.println("前置");
}
@After("com.bjsxt.test.Demo.demo1()")
public void myafter(){
System.out.println("后置通知");
}
@AfterThrowing("com.bjsxt.test.Demo.demo1()")
public void mythrow(){
System.out.println("异常通知");
}
@Around("com.bjsxt.test.Demo.demo1()")
public Object myarround(ProceedingJoinPoint p) throws
Throwable{
System.out.println("环绕-前置");
Object result = p.proceed();
System.out.println("环绕-后置");
return result;
}
}
七.自动注入
在 Spring 配置文件中对象名和 ref=”id”id 名相同使用自动注入,可以不配置<property/>
配置方法:
1.<bean>中配置autowire
2.<beans>中配置default-autowire
注意范围:
<bean>只对当前<bean>生效,<beans>对全局文件生效
参数详解:
①default 默认查找全局,不配置就是no
②no 不适用自动注入
③byName 通过名字查找
④byType 通过类型查找
⑤constructor通过构造器 底层使用的是byName
八.使用Spring加载properties文件
1.创建properties文件
2.Spring中引入Context
3.xml中定义文件读取
4.使用获得参数
详解:
举例 使用配置数据源dataSource
1.不多赘述,看图
2.application.xml中引入context命名
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byName">
3.xml中使用<context:property-placeholder>标签,定位文件位置,便于读取
<context:property-placeholder location="classpath:db.properties"/>
4.使用${"key"}获得值
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
8.2在Spring管理的类中获得properties文件配置的数据
1.创建properties文件
2.xml中创建扫描器
3.类中配置@Value()获取值
详解:
1.同上
2.xml中使用<context:component-scan>扫描需要使用标签的类,告诉Spring你的哪些包配置了注解
<context:component-scan base-package="com.sshqx.service.impl.UsersServiceImpl"></context:component-scan>
3.在类中使用@Value("${key}")获得值
@Value("${jdbc.username}")
public String test;
九.Scope属性
<bean>标签下的属性,用来表示类的(单例,多例 有效范围等)
可取值
1.singleton 单例
2.prototype 多例
3.request 每次请求实例化
4.session 每次会话实例化
5.application application对象内实例化一次
6.global session : spring 推 出 的 一 个 对 象 , 依 赖 于spring-webmvc-portlet ,类似于 session
十.声明式事务
声明式事务是基于AOP基础,他和AOP很像,简单点说AOP是拦截的类,而声明式事务拦截的是方法
而且方法全位于service.impl包下的方法
1.编程式事务
值得是由程序员来编写的事物控制代码,例如:过滤器openSessionInview的编写
2.声明式事务
事务控制代码已经有Spring帮我妈写好了,我们只需声明使用哪些方法和方法的范围
3.配置流程
①声明命名域
②创建事物管理类
③配置哪些方法需要事物管理以及范围
④完善AOP切面
详细:
1.自己找下吧
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
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/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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byName">
2.
<!-- 配置事物管理 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"></bean>
3.详细参数后面在写
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="ins*" />
<tx:method name="upd*" />
<tx:method name="del*" />
<tx:method name="*" />
</tx:attributes>
</tx:advice>
4.
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
六.声明式事务中属性解释
1. name=”” 哪些方法需要有事务控制
1.1 支持*通配符
2.readonly="true"是否是只读事物,默认值是false;开启后自动优化查询事物
所以只要是查询就开
3.propagation控制事物传播行为
3.1 当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务(新建事务?在事务中执行?把事务挂起?报异常?)
3.2 REQUIRED (默认值): 如果当前有事务,就在事务中执行,如果当前没有事务,新建一个事务.
3.3 SUPPORTS:如果当前有事务就在事务中执行,如果当前没有事务,就在非事务状态下执行.
3.4 MANDATORY:必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错.
3.5 REQUIRES_NEW:必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,把当前事务挂起.
3.6 NOT_SUPPORTED:必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前事务挂起.
3.7 NEVER:必须在非事务状态下执行,如果当前没有事务,正常执行,如果当前有事务,报错.
3.8 NESTED:必须在事务状态下执行.如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务.
4. isolation=”” 事务隔离级别
多线程以及并发访问怎么保证数据完整性
1.脏读
针对查询
脏读又称无效数据的读出,是指在数据库访问中,事物T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。
两个事物,事物A读取出数据,此时事物B尚未提交,则A读出数据与数据库数据不一致,,脏读
2.不可重复读
针对修改
不可重复读,是指在数据库访问中,一个事物范围内两个相同的查询却返回了不同数据。
一个事物,第一次读取没问题(事物A),事物B建立在事物A基础上进行了修改操作,使得事物A再次读取数据前后不一致
3.幻读
针对增加,删除
事物A查询操作之后事物B插入了相同条件了数据,或者删除了原数据,相当于幻觉,叫幻读
4.5 DEFAULT: 默认值,由底层数据库自动判断应该使用什么隔离界
别
4.6 READ_UNCOMMITTED: 可以读取未提交数据,可能出现脏读,不重复读,幻读.
4.6.1 效率最高.
4.7 READ_COMMITTED:只能读取其他事务已提交数据.可以防止脏读,可能出现不可重复读和幻读.
4.8 REPEATABLE_READ: 读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读.脏读,可能出现幻读.
4.9 SERIALIZABLE: 排队操作,对整个表添加锁.一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表.
4.9.1 最安全的
4.9.2 效率最低的.
5. rollback-for=”异常类型全限定路径”
5.1 当出现什么异常时需要进行回滚
5.2 建议:给定该属性值.
5.2.1 手动抛异常一定要给该属性值.
6. no-rollback-for=””
6.1 当出现什么异常时不滚回事务.
七. Spring 中常用注解.
1. @Component 创建类对象,相当于配置<bean/>
2. @Service 与@Component 功能相同.
2.1 写在 ServiceImpl 类上.
3. @Repository 与@Component 功能相同.
3.1 写在数据访问层类上.
4. @Controller 与@Component 功能相同.
4.1 写在控制器类上.
5. @Resource(不需要写对象的 get/set)
5.1 java 中的注解
5.2 默认按照 byName 注入,如果没有名称对象,按照 byType 注入
5.2.1 建议把对象名称和 spring 容器中对象名相同
6. @Autowired(不需要写对象的 get/set)
6.1 spring 的注解
6.2 默认按照 byType 注入.
7. @Value() 获取 properties 文件中内容
8. @Pointcut() 定义切点
9. @Aspect() 定义切面类
10. @Before() 前置通知
11. @After 后置通知
12. @AfterReturning 后置通知,必须切点正确执行
13. @AfterThrowing 异常通知
14. @Arround 环绕通知