Spring

  • Spring是一个开源框架,它由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson)创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
  • Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
  • Rod Johnson: Spring Framework创始人,著名作者。 Rod在悉尼大学不仅获得了计算机学位,同时还获得了音乐学位。更令人吃惊的是在回到软件开发领域之前,他还获得了音乐学的博士学位。 有着相当丰富的C/C++技术背景的Rod早在1996年就开始了对Java服务器端技术的研究。

1.优点:

spring是一个开源的免费框架(容器)

spring是一个轻量级、非入侵式的框架(引入jar包即可用,不会和原项目有影响)

控制反转(IOC),面向切面(AOP)

支持事务处理,对框架整合的支持

总结一句话:spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

2.组成:


3.扩展

在Spring的官网有介绍:现代化的java开发!就是基于Spring的开发。

  • Spring Boot

    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速的开发单个微服务
    • 约定大于配置
  • Spring Cloud
    • SpringCloud是基于SpringBoot实现的

大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring以及SpringMVC

IOC理论推导

从本质上解决了问题,系统的耦合性大大降低,可以专注在业务的实现上!这就是IOC的原型

1.IOC本质

**控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法。**没有IOC的程序中,使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection,DI)

对象由Spring来创建,管理,装配

IOC创建对象的方式

在配置文件加载时,容器中管理的对象就已经初始化了!

1.使用无参构造方法(默认)

2.使用有参构造创建对象

  • 下标赋值

    <bean id="user" class="com.lhl.entity.User"><constructor-arg index="0" value="1"/>
    </bean>
    
  • 参数名

    <!--第三种,直接通过参数名来设置-->
    <bean id="user" class="com.lhl.entity.User"><constructor-arg name="id" value="1"/>
    </bean>
    
  • 类型

    <!--第二种方式通过类型创建,不建议使用-->
    <bean id="user" class="com.lhl.entity.User"><constructor-arg type="int" value="1"/>
    </bean>
    

Spring配置

1.别名

<!--别名,给了别名,也可以使用这个别名获取到这个对象-->
<alias name="user" alias="user1"/>

2.Bean的配置

<!--id:bean的唯一标识符,相当于对象名calss:bean对象所对应的全限定名:包名+类型name:也是别名,而且name更加强大,可以同时取多个别名可以使用多种符号分隔别名
-->
<bean id="user" class="com.lhl.entity.User" name="user1 user2,user3;user4">
</bean>

3.Import

import,一般用于团队开发,可以将多个配置文件,导入合并为一个

假设项目有多个人开发,每个人开发不同的模块,不同的类注册在不同的bean中,我们可以利用import将所有人的beanc.xml合并为一个总的!

  • 依依
  • 尔尔
  • 姗姗
  • applicationContext.xml
<import resource="bean1.xml"/>
<import resource="bean2.xml"/>
<import resource="bean3.xml"/>

使用的时候,直接使用总的配置就可以了

依赖注入

1.构造器注入

public class User {private String name;private int age;private String sex;public User(String name, int age, String sex) {this.name = name;this.age = age;this.sex = sex;}public User() {}@Overridepublic String toString() {return "User{name=" + name +", age=" + age +", sex='" + sex "}";}
}

方式一:属性名注入

<!--通过属性名注入-->
<bean class="com.lhl.pojo.User" id="user1"><constructor-arg name="name" value="木木1"></constructor-arg><constructor-arg name="age" value="201"></constructor-arg><constructor-arg name="sex" value="男1"></constructor-arg>
</bean>

方式二:参数位置索引注入

<!--通过参数位置索引注入-->
<bean class="com.lhl.pojo.User" id="user2"><constructor-arg index="0" value="木木2"></constructor-arg><constructor-arg index="1" value="202"></constructor-arg><constructor-arg index="2" value="男2"></constructor-arg>
</bean>

2.Set方式注入【重点】

  • 依赖注入:Set注入

    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有属性,由容器来注入
  • 复杂类型

    public class Address {private String name;//set/get方法  toString方法
    }
    
  • 真实对象

    public class Student {//set/get方法  toString方法private Integer id;private String name;private Address address;private String[] girlFriends;private List<String> hobbies;private Map<String,String> games;private Set<String> cards;
    }
    
  • 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="address" class="com.lhl.entity.Address"><property name="name" value="江西人江西魂"></property></bean><bean id="student" class="com.lhl.entity.Student"><property name="id" value="1"></property><property name="name" value="依依"></property><property name="address" ref="address"></property><!--两种方式都可以注入--><!--<property name="girlFriends" value="依依,尔尔,姗姗"></property>--><property name="girlFriends"><array><value>依依</value><value>尔尔</value><value>姗姗</value></array></property><property name="hobbies"><list><value>篮球</value><value>乒乓球</value><value>羽毛球</value></list></property><property name="games"><map><entry key="端游" value="英雄联盟"></entry><entry key="手游" value="王者荣耀"></entry><entry key="桌游" value="三国杀"></entry></map></property><property name="cards"><set><value>学生证</value><value>饭卡</value><value>热水卡</value></set></property></bean>
    </beans>
    
  • 测试

        @org.junit.Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");Student student = (Student) context.getBean("student");System.out.println(student);}
    
  • 结果

    Student{id=1, name='依依', address=Address{name='江西人江西魂'}, girlFriends=[依依, 尔尔, 姗姗], hobbies=[篮球, 乒乓球, 羽毛球], games={端游=英雄联盟, 手游=王者荣耀, 桌游=三国杀}, cards=[学生证, 饭卡, 热水卡]}
    

3.扩展方式注入

引用命名空间(p,c)

4.bean作用域

  • 单例模式(默认机制)

    <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
    

  • 原型模式(每次从容器中获取的时候,都会产生一个新对象)

    <bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
    

  • request、session、application只能在web开发中使用到

bean的自动装配

  • 自动装配是Spring满足bean依赖一种方式
  • Spring会在上下文中自动寻找,并自动给bean装配属性

Spring中三种装配 的方式

  1. 在xml中显示配置
  2. 在java中显示配置
  3. 隐式的自动装配bean【重要】

1.ByName自动装配

<bean id="dog" class="com.lhl.entity.Dog"></bean>
<bean id="cat" class="com.lhl.entity.Cat"></bean>
<bean id="proper" class="com.lhl.entity.Proper" autowire="byName">

2.ByType自动装配

<bean id="dog" class="com.lhl.entity.Dog"></bean>
<bean id="cat" class="com.lhl.entity.Cat"></bean>
<bean id="proper" class="com.lhl.entity.Proper" autowire="byType">

小结:

  • byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
  • byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致

3.使用注解实现自动装配

使用须知:

  1. 导入约束(context约束)
  2. 配置注解的支持 (context:annotation-config/)【重要】
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/>
</beans>

@Autowired

直接在属性上使用即可,前提是自动装配的属性在(Spring)容器中存在

科普:

@Nullable   字段标记了这个注解,说明这个字段可以为null

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value=“xxx”)去配置@Autowired的使用,指定一个唯一的bean对象注入

@Resource注解

public class Proper {@Resource(name = "dog")private Dog dog;@Resourceprivate Cat cat;
}

小结:

​ @Resource和@Autowired 的区别:

  • 都是用来自动装配的,都可以放在属性字段上
  • @Autowired 通过bytype的方式实现,要求这个对象必须存在
  • @Resource 默认通过byname的方式实现,如果找不到名字,则通过bytype实现。都找不到的情况下报错
  • 执行顺序不同:@Autowired 通过bytype的方式实现,@Resource 默认通过byname的方式实现

使用注解开发

在使用spring4之后,要使用注解开发,必须保证aop的包导入了

使用注解需要引入context命名空间,增加注解支持

<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/><context:component-scan base-package="com.lhl.entity"/>
</beans>

1.bean

2.属性如何注入

@Component
public class Student {public String name;//相当于  <property name="name" value="木木"></property>    @Value(value = "木木")public void setName(String name) {this.name = name;}
}

3.衍生的注解

@Component有几个衍生注解,在web开发中,会按照MVC三层架构分层

  • dao 【@Repository】
  • service 【@Service】
  • controller 【@Controller】

这四个注解功能一样,都是代表将某个类注册到Spring中,装配Bean

4.自动装配

-@Autowired:自动装配通过类型--名字如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="xxx")
-@Nullable:字段标记了这个注解,说明这个字段可以为null
-@Resource:自动装配通过名字--类型

5.作用域

@Component
@Scope(value = "singleton")//作用域--单例模式
public class Student {public String name;//相当于  <property name="name" value="木木"></property>@Value(value = "木木")public void setName(String name) {this.name = name;}
}

6.小结

xml与注解:

  • xml: 比较适用,维护简单
  • 注解: 维护相对复杂

xml与注解最佳实践:

  • xml 用来管理bean
  • 注解负责完成属性的注入
  • 使用注解的过程中,需要注意开启注解的支持
<context:annotation-config/>
<context:component-scan base-package="com.lhl.entity"/>

使用java的方式配置spring

不使用spring的xml配置,全权交给java做

在以前javaConfig是Spring的一个子项目,在Spring4之后,成为了一个核心功能

1.实体类

//这个类被Spring接管,注册到容器中
@Component
public class User {private String name;public String getName() {return name;}@Value(value = "木木")//属性注入值public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{name='" + name +"}";}
}

2.配置类

//  Spring容器托管,注册到容器中,@Configuration本来就是一个@Component
//  @Configuration代表这是一个配置类,和applicationContext.xml实现的功能一样
@Configuration
@ComponentScan("com.lhl")
@Import(ApplicationConfig2.class)
public class ApplicationConfig {//注册一个bean,就相当于applicationContext中的bean标签//方法的名字,相当于bean标签中的id属性//方法的返回类型,相当于bean标签中的class属性@Beanpublic User user(){return new User();}
}

3.测试

public class Test {@org.junit.Testpublic void test1(){//完全使用配置类方式去做,只能通过AnnotationConfigApplicationContext上下文来获取容器,通过配置类的class对象加载ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);User user = context.getBean("user", User.class);System.out.println(user);}
}

代理模式

  • 使操作更加纯粹,不用去关注其他业务
  • 公共业务也可以交给代理,实现业务分工
  • 公共业务发生扩展的时候,方便集中管理

1.静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,一般会做附属操作
  • 客户:访问代理对象的人

代码步骤:

  1. 接口

    public interface Rent {void rent();
    }
    
  2. 真实角色

    public class Host implements Rent{public void rent() {System.out.println("房东出租房子");}
    }
    
  3. 代理角色

    public class Proxy implements Rent{private Host host;public Proxy() {}public Proxy(Host host) {this.host = host;}public void rent() {host.rent();landlord();seeHouse();}public void landlord(){System.out.println("签租赁合同");}public void seeHouse(){System.out.println("看房子");}
    }
    
  4. 客户端访问代理角色

    public class Me {public static void main(String[] args) {Host host = new Host();Proxy proxy = new Proxy(host);proxy.rent();System.out.println("房东");}
    }
    

代理模式的好处:

  • 可以使真实角色的操作更加纯粹,不用去关注公共业务
  • 公共就交给代理角色!实现业务的分工
  • 公共业务发生扩展的时候,方便集中管理

缺点:

  • 一个真实角色就会产生一个代理角色,代码量会翻倍~效率低

3.动态代理

  • 动态代理和静态代理角色一样

  • 动态代理的代理类是动态生成的,不是直接写好的

  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理

    • 基于接口–JDK动态代理
    • 基于类:cglib
    • java字节码实现:javasist

需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序

动态代理的好处:

  • 可以使真实角色的操作更加纯粹,不用去关注公共业务
  • 公共就交给代理角色!实现业务的分工
  • 公共业务发生扩展的时候,方便集中管理
  • 一个动态代理类代理的是一个接口,一般就是对应这个接口的业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口
public class ProxyInvocationHandler implements InvocationHandler {private Object object;public void setObject(Object object) {this.object = object;}public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this);}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//增加业务的方法log(method.getName());return method.invoke(object,args);}//要新添加的业务public void log(String name){System.out.println("使用了"+name+"方法");}
}
public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl();ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();proxyInvocationHandler.setObject(userService);UserService proxy = (UserService) proxyInvocationHandler.getProxy();proxy.delete();proxy.add();
}

AOP

1.什么是AOP

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

2.AOP在Spring中的作用

提供声明式事务;允许用户自定义切面

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与业务逻辑无关,但是需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等…
  • 切面(ASPECT):横切关注点 被模块化的 的特殊对象。类
  • 通知(Advice):切面必须要完成的工作。方法
  • 目标(Target):被通知的对象
  • 代理(Proxy):向目标对象应用通知之后创建的对象
  • 切入点(PointCut):切面通知 执行的“地点”的定义
  • 连接点(JointPoint):与切入点匹配的执行点

SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:

即AOP在不改变原有代码的情况下,去增加新的功能

3.使用Spring实现AOP

Aspectj切入点语法定义

在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut”切入点”

例如定义切入点表达式 execution (* com.sample.service.impl…****. ****(…))

execution()是最常用的切点函数,其语法如下所示:

整个表达式可以分为五个部分:

1、execution(): 表达式主体。

2、第一个*号:表示返回类型, *号表示所有的类型。

3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。

4、第二个*号:表示类名,*号表示所有的类。

5、*(…):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数

【使用AOP,需要导入一个依赖包】

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.2</version>
</dependency>

方式一:

使用springAPI接口【SpringAPI接口实现】

public class Log implements MethodBeforeAdvice{public void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName()+"执行了"+method.getName());}
}
<?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.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean class="com.lhl.dao.UserDaoImpl" id="userDao"/><bean class="com.lhl.log.Log" id="log"/><!--方式一:使用原生spring API接口--><aop:config><aop:pointcut id="pointcut" expression="execution(* com.lhl.dao.UserDaoImpl.*(..))"/><aop:advisor advice-ref="log" pointcut-ref="pointcut"/></aop:config>
</beans>

方式二:

自定义来实现AOP【切面定义】

public class DiyPointCut {public void before() {System.out.println("===方法执行前===");}public void after() {System.out.println("===方法执行后===");}
}
<!--方式二:自定义类-->
<bean class="com.lhl.diy.DiyPointCut" id="cut"/><aop:config><!--自定义切面,ref 要引用的类--><aop:aspect ref="cut"><!--切入点--><aop:pointcut id="point" expression="execution(* com.lhl.dao.UserDaoImpl.*(..))"/><!--通知--><aop:after method="after" pointcut-ref="point"/><aop:before method="before" pointcut-ref="point"/></aop:aspect>
</aop:config>

方式三:

注解实现AOP

@Aspect
public class AnnotationPointCut {@Before("execution(* com.lhl.dao.UserDaoImpl.*(..))")public void before(){System.out.println("===执行之前===");}@After("execution(* com.lhl.dao.UserDaoImpl.*(..))")public void after(){System.out.println("===执行之后===");}@Around("execution(* com.lhl.dao.UserDaoImpl.*(..))")public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("===环绕之前===");Object proceed = joinPoint.proceed();System.out.println("===环绕之后===");}
}
<!--方式三-->
<bean class="com.lhl.diy.AnnotationPointCut" id="annotationPointCut"/>
<!--JDK(默认 proxy-target-class="false")  cglib(proxy-target-class="true")-->
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

环绕通知结果

===环绕之前===
===执行之前===
增加
===执行之后===
===环绕之后===

整合Mybatis

mybatis-spring中文文档 http://mybatis.org/spring/zh/index.html

1.编写数据源配置

sqlsessionFactory

SQLSessionTemplate

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--读取properties文件--><context:property-placeholder location="classpath:db.properties" system-properties-mode="FALLBACK"/><!--DataSoure:使用的数据源替换Mybatis的配置c3p0 dbcp druid我们这里使用的jdbc:org.springframework.jdbc.datasource--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" ><property name="driverClassName" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></bean><!--sqlSessionFactory--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><!--绑定Mybatis配置文件--><property name="configLocation" value="classpath:mybatis-config.xml"/><property name="mapperLocations" value="classpath:com/ramelon/mapper/*.xml"/></bean><!--SqlSessionTemplate就是我们使用的sqlsession--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!--只能只用构造器注入sqlSessionFactory,因为它没有set方法--><constructor-arg index="0" ref="sqlSessionFactory"/></bean>
</beans>

2.给接口加实现类

public class StudentDaoImpl implements StudentDao {private SqlSession sqlSession;public SqlSession getSqlSession() {return sqlSession;}public void setSqlSession(SqlSession sqlSession) {this.sqlSession = sqlSession;}public List<Student> students() {StudentDao mapper = sqlSession.getMapper(StudentDao.class);return mapper.studes();}
}

3.将实现类,注册到spring容器中

<bean id="userMapper2" class="com.ramelon.dao.UserMapperImpl2"><property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

4.测试

@Test
public void selectUser(){ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");UserMapper userMapper = context.getBean("userMapper2",UserMapper.class);List<User> users = userMapper.selectUser();for (User user : users) {System.out.println(user);}
}

方法二

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {public List<User> selectUser() {return getSqlSession().getMapper(UserMapper.class).selectUser();}
}

SqlSessionDaoSupport 是一个抽象的支持类,用来为你提供 SqlSession。调用 getSqlSession() 方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法。

声明式事务

1.回顾事务

  • 一组业务当成一个业务走;要么都成功,要么都失败
  • 事务在项目开发中十分重要,涉及到数据的一致性问题
  • 确保完整性和一致性

事务ACID原则

  • 原子性(Atomicity)

    • 一个事务中的所有操作要么全部成功提交,要么全部失败回滚。
  • 一致性(Consistency)
    • 事务操作不能破坏数据的一致性,数据库在一个事务的执行前后都应处于一致性状态。
  • 隔离性(Isolation)
    • 隔离性指数据库并发情况下,并发的事务直接是隔离的,一个事务的执行不能被其他事务影响。隔离性比较复杂,在MySQL中存在四种隔离级别:Read Uncommitted、Read Committed、Repeatable Read和Serializable,不同的隔离级别采用不同的锁机制实现。
  • 持久性(Durability)
    • 持久性指一旦事务提交,则其对数据的变更就是永久性的,即使数据库发生任何故障都不应该对数据造成任何影响。

2.spring中的事务管理

  • 声明式事务:AOP
  • 编程式事务:需要在代码中,进行事务的管理

为什么需要事务?

  • 如果不配置事务,可能会存在数据提交不一致的情况
  • 如果不在spring中配置声明式事务,需要在代码中手动提交事务
  • 事务在项目开发中十分重要,涉及到数据的一致性问题

Spring相关知识点笔记

IOC(控制反转)

​ https://www.cnblogs.com/xdp-gacl/p/4249939.html

在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。

所以控制反转IOC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IOC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IOC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IOC容器了,通过IOC容器来建立它们之间的关系。

这是我对Spring的IOC**(控制反转)的理解。DI(依赖注入)**其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。

DI(依赖注入)

IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

理解了IOC和DI的概念后,一切都将变得简单明了,剩下的工作只是在spring的框架中堆积木而已。

JAVA反射机制(一种JAVA的特性)

说全

Java反射机制是在运行状态中,对于任意一个类(Class文件),都能够知道这个类的属性和方法;对于任意一个对象都能调用它的方法和属性;这种动态获取的信息以及调用对象的方法的功能称为java语言的反射机制。

说简

动态获取类中的信息,就是java反射机制。 可以理解为对类的解剖。只是获得它的字节码(class对象)。

AOP(切面编程)

BeanPostProcessor

@Aspect
public class MyAspect{// 定义切入表达式@Pointcut(value = "execution(* com.spring.aop.SmartMonkey.*(..))")public void myPointCut() {// 调用例子: @Before(value="myPointCut()")}
}

advice 的类型

before advice, 在 join point 前被执行的 advice. 虽然 before advice 是在 join point 前被执行, 但是它并不能够阻止 join point 的执行, 除非发生了异常(即我们在 before advice 代码中, 不能人为地决定是否继续执行 join point 中的代码)

after return advice, 在一个 join point 正常返回后执行的 advice

after throwing advice, 当一个 join point 抛出异常后执行的 advice

after(final) advice, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice.

around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是最常用的 advice.

@Before("execution(public float com.spring.aop.SmartDog.*(*, *))")
public void showStartLog(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();String name = signature.getName();Object[] args = joinPoint.getArgs();System.out.println("前置通知" + " 目标方法名是" + name + " 参数" + Arrays.asList(args));
}@AfterReturning(value = "execution(public float com.spring.aop.SmartDog.*(..))", returning = "tnres")
public void showSuccessLog(Object tnres) {System.out.println("返回通知" + " 结果是" + tnres);
}@AfterThrowing(value = "execution(public float com.spring.aop.SmartDog.*(..))", throwing = "throwable")
public void showExceptionLog(Throwable throwable) {System.out.println("异常通知" + throwable);
}@After("execution(public float com.spring.aop.SmartDog.*(..))")
public void showFinallyLog() {System.out.println("最终通知");
}/*** 环绕通知*/
@Around(value = "execution(public float com.spring.aop.SmartDog.*(..))")
public Object doAround(ProceedingJoinPoint joinPoint) {Object result = null;Signature signature = joinPoint.getSignature();String name = signature.getName();Object[] args = joinPoint.getArgs();try {// 前置通知System.out.println("前置通知" + " 目标方法名是" + name + " 参数" + Arrays.asList(args));// 调用目标方法result = joinPoint.proceed();System.out.println("返回通知" + " 结果是" + result);} catch (Throwable e) {// TODO: handle exceptionSystem.out.println("异常通知" + e.getMessage());}finally {System.out.println("最终通知");}return result;
}

jdk动态代理

JDK动态代理是代理模式的一种实现方式,其只能代理接口。

使用步骤

1、 新建一个接口

2、 为接口创建一个实现类

3、 创建代理类实现java.lang.reflect.InvocationHandler接口

4、 测试

日志打印

静态对象 动态对象 通过底层BeanPostProcessor方法,对象都存放在map中,需要用到直接get

aop : https://blog.csdn.net/q982151756/article/details/80513340

单进程单线程:一个人在一个桌子上吃菜

单进程多线程:多个人在同一个桌子上一起吃菜

多进程单线程:多个人每个人在自己的桌子上吃菜。

森亏nice的 synchronized:判断线程是否被霸占,是则等待,反之,占用。

https://www.cnblogs.com/jmsjh/p/7762034.html

java 集合框架

Iterator

Collection

Map接口

LinkedList

面试题 https://www.cnblogs.com/chenmingjun/p/8745646.html

Arrays.asList(args));

    // 调用目标方法result = joinPoint.proceed();System.out.println("返回通知" + " 结果是" + result);} catch (Throwable e) {// TODO: handle exceptionSystem.out.println("异常通知" + e.getMessage());
}finally {System.out.println("最终通知");
}
return result;

}


# jdk动态代理JDK动态代理是代理模式的一种实现方式,其只能代理接口。### 使用步骤1、 新建一个接口2、 为接口创建一个实现类3、 创建代理类实现java.lang.reflect.InvocationHandler接口4、 测试日志打印![img](https://img-blog.csdnimg.cn/20190916094257360.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTMwOTQwMg==,size_16,color_FFFFFF,t_70)静态对象 动态对象 通过底层BeanPostProcessor方法,对象都存放在map中,需要用到直接getaop : https://blog.csdn.net/q982151756/article/details/80513340单进程单线程:一个人在一个桌子上吃菜 单进程多线程:多个人在同一个桌子上一起吃菜 多进程单线程:多个人每个人在自己的桌子上吃菜。森亏nice的 synchronized:判断线程是否被霸占,是则等待,反之,占用。https://www.cnblogs.com/jmsjh/p/7762034.htmljava 集合框架### Iterator### Collection### Map接口LinkedList面试题 https://www.cnblogs.com/chenmingjun/p/8745646.html

Spring 自学笔记相关推荐

  1. 牛小刚的Spring自学笔记之IOC

    牛小刚的Spring自学笔记之IOC,DI 1.啥是IOC,DI IOC就是控制反转,将类的创建啥的控制权交给IOC容器,不用你new ,IOC容器给你new.你需要啥对象直接从IOC容器中拿就可以了 ...

  2. 牛小刚的Spring自学笔记之搭建环境

    1.搭建spring框架的环境 先下载spring包,下载地址在这点这里 下载名为 spring-framework-4.3.0.RELEASE-dist.zip 的文件 解压就好了 也可以选择mav ...

  3. Spring框架自学笔记

    Spring框架自学笔记 第一章 简介 Spring是一套建筑标准,比如承重标准.丈量标准,通风标准等,并规范了结构:框架式结构,浇筑式结构,且定义了建筑的每个组成部分名字与接口,比如电力系统的接口是 ...

  4. 字节、阿里等大厂的技术如何?看看这些Java程序员的自学笔记

    这份笔记涉及JVM.JAVA集合.JAVA多线程并发.JAVA基础.Spring原理.微服务.Netty与RPC.网络.日志.Kafka.RabbitMQ.Hbase.MongoDB.设计模式.负载均 ...

  5. SpringMVC自学笔记

    SpringMVC自学笔记 视频:BV1aE41167Tu 官方文档:https://docs.spring.io/spring-framework/docs/current/reference/ht ...

  6. 字节跳动大佬的Python自学笔记.pdf

    1. 字节跳动大佬的Python自学笔记 这是我的一个朋友自学资料包,通过这个资料包自学拿到了字节跳动的Offer, 下面是他之前入门学习Python时候的学习资料,非常全面,从Python基础.到w ...

  7. JAVA自学笔记07

    JAVA自学笔记07 1.构造方法 1) 例如:Student s = new Student();//构造方法 System.out.println(s);// Student@e5bbd6 2)功 ...

  8. 【Spring学习笔记-MVC-13.2】Spring MVC之多文件上传

    作者:ssslinppp       1. 摘要 前篇文章讲解了单文件上传<[Spring学习笔记-MVC-13]Spring MVC之文件上传>http://www.cnblogs.co ...

  9. MySQL自学笔记2--select的5个子句

    MySQL自学笔记 使用的MySQL自带命令客户端,其中具体的操作是在自建的数据库下room303表中进行的,表中的列有:id.name.age.email.tel.salary.riqi.class ...

最新文章

  1. PHP----------PHP自身的性能优化注意事项
  2. java mysql 触发器 存储过程_mysql 触发器 存储过程 java调用
  3. 7、C语言 —— 字符串常用处理函数
  4. 【项目合作】指甲识别与实时渲染
  5. Day 4 列表,元组,range
  6. db link的查看创建与删除
  7. java的几个概念AOP、IOC、DI、DIP、工厂模式、IOC容器
  8. 采集企业联系方式的10个经典方法
  9. Python之文本去重(基础版)
  10. 180720_有道词典离线增强版添加词库(小众知识)
  11. Redis雪崩效应的解决方案(转)
  12. 小心 transmittable-thread-local 的这个坑
  13. python假设检验
  14. 网页版python编辑器-史上超强 Python 编辑器,竟然是张网页?!
  15. 在 Linux中安装中文输入法
  16. android里面字体的设置,Android中字体设置Font
  17. 2013再见,2014,在路上
  18. 不同大小硬盘对拷oracle,大小不一样的硬盘怎么实现对拷?
  19. Windows系统下为 Python安装 Pcapy模块的方法
  20. 30 个免费的 Sketch 必备插件

热门文章

  1. DD语录201105
  2. gtasa联机服务器注册,GTA SA:MP 0.1 联机服务器建设全教程(XP系统)
  3. linux学习笔记-2
  4. collect_set 如何有序
  5. 小白自学笔记——JAVA基础 1.5API文档说明
  6. Centos 7加入Windows AD域及搭建基于Windows AD域(即ldap)认证的samba共享
  7. 《最优化理论与算法》(陈宝林)——第9章:一维搜索
  8. wow工作室脚本_打击工作室的脚本排队行径,魔兽健康环境从我做起!
  9. (附源码)springboot大学生社团管理系统的设计与实现 毕业设计150912
  10. oracle p6 16.1,Oracle Primavera P6 Pro R16.1单机版安装教程