Spring5-基础知识

Spring

1. Spring的基本概述

  • spring是一个轻量级的JAVAEE的开源框架

  • spring可以解决企业级应用开发的复杂性

  • spring有两个核心部分IOC和AOP:

    IOC:控制反转,把创建对象的过程交给spring进行管理

    AOP:面向切面,在不修改源代码的情况下进行功能的增强

  • spring的特点:

    方便解藕,简化开发

    Aop编程的支持

    方便测试的集成

    方便和其他的框架进行整合

    方便进行事务的操作和降低api的使用难度


2. IOC容器

2.1 什么是IOC?

  • 控制反转,把对象创建和对象之间的调用过程,全部交给spring来进行管理

  • 使用IOC的目的就是为了降低耦合度

  • IOC思想基于IOC容器完成,底层就是对象工厂

  • Spring提供IOC容器实现的两种实现方式:

    BeanFactory:

    IOC容器的基本实现,是spring内部的使用接口,不提供开发人员进行使用,加载配置文件的时候不会进行对象的创建,在使用的时候才会进行对象的创建

    ApplicationContext:

    BeanFactory的子接口,提供了更加强大的功能,一般由开发人员进行使用,加载配置文件的时候,对象就会进行创建

    ApplicationContex有实现类:

    FileSystemXmlApplicationContext: 当前类在系统盘的路径地址

    ClassPathXmlApplicationContext: 当前类在src下的路径地址

2.2 IOC的底层实现原理

xml解析/工厂模式/反射

第一步xml配置文件,配置创建的对象,第二步创建工厂类根据反射创建对象

2.3 Bean的两种类型

  • 普通bean:在配置文件中定义的是什么类型就返回什么类型

  • 工厂bean:在配置文件中定义的类型可以和返回类型不一致,实现FactoryBean,重写getObject方法

2.4 Bean的作用域

spring创建的bean分为单实例和多实例

spring默认创建的bean是单实例的

设置单实例还是多实例的方式:

设置bean标签scope,单实例scope=“singleton”,多实例scope=“prototype”,加载配置文件的时候并会创建bean

设置了多实例scope=“prototype”之后。加载配置文件的时候并不会创建bean,会在getBean的时候进行对象的创建

2.5 Bean的生命周期

<!--定义:一个对象从创建到销毁的过程-->

  1. 通过构造去创建bean的实例,(无参构造)

  2. 为bean的数据设置值和其他bean引用(调用set方法)

  3. (初始化之前调用前置处理器 )-实现BeanPostProcessor

  4. 调用bean的初始化方法(需要进行配置)

  5. (初始化之后调用后置处理器)-实现BeanPostProcessor

  6. bean可以使用了(对象获取到了)

  7. 当容器关闭的时候调用bean的销毁方法(需要进行配置)

2.6 IOC操作Bean的管理

什么是自动装配?

spring根据指定的装配规则(属性名称或者属性类型),将属性值注入

xml的自动装配:在bean标签增加autowire属性:byName:根据名称进行注入byType:根据type进行注入

注意:根据类型匹配时候,如果有相同类型的两个bean就会报错,不知道选择哪个bean进行注入

2.7 IOC操作Bean基于注解方式

什么是注解?

注解是一种特殊的代码标记,用来作用到类,方法,属性上面,格式:@注解名称(属性名称=属性值,...),使用的目的就是可以简化开发

spring针对Bean的管理中创建对象提供的注解:

@Component:一种普通的注解通过他都可以创建对象,相当于xml中的 bean标签

@Service:一般用在业务逻辑层

@Controller:一般用在web层

@Repository:一般用在dao层

注意:上面的四个注解功能一样,都可以创建bean的实例

spring注解方式实现属性的注入

@AutoWired:根据属性类型进行注入

@Qualifier:根据属性名称进行注入(和@AutoWired组合使用)

@Resource:可以根据属性类型进行注入,也根据属性名称进行注入

@Value:注入普通类型属性

完全注解开发

(1)创建配置类,替代xml

@Configuration(作为配置类)

@ComponentScan(basePackages=“扫描的包地址”)

@Configuration
@ComponentScan(basePackages = {"com.wrh.spring"})
public class SpringConfig {
}

通过new AnnotationConfigApplicationContext(“类名”)加载

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

3. AOP

什么是aop?

aop就是面向切面的编程,利用AOP可以对业务逻辑的各个部分进行隔离,这样可以使业务逻辑之间的耦合度降低,提高程序的重用性,同时提高了开发效率,可以在不修改源代码的基础上进行功能的增强

底层原理:aop使用动态代理的方式实现

3.1代理的两种方式:

(1)有接口的情况下:使用jdk的动态代理

<!--创建接口实现类的代理对象,在代理对象的基础上进行增强-->

(2)无接口的情况下:CGLIB动态代理

<!--创建对象的子类的代理对象,在代理对象的基础上进行增强-->

aop-jdk的动态代理:

(1)调用newProxyIntance

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

ClassLoader loader:类加载器

Class<?>[] interfaces:增强方法所在的类,这个类实现的接口,支持多个接口

InvocationHandler h:实现InvocationHandler的对象,创建代理对象,写增强方法

(2)jdk代理代码实现:

/**
 * @author wangruiheng
 */
public class JdkProxy {
    public static void main(String[] args) {
        //接口对象
        Class<?>[] interfaces = {UserDao.class};
        //接口实现的方法-需要增强的类
        UserDaoImpl userDaoImpl = new UserDaoImpl();
        UserDao userDao = (UserDao)Proxy.newProxyInstance(JdkProxy.class.getClassLoader(),interfaces,new UserDaoInvocationHandler(userDaoImpl));
        userDao.add(1, 2);
    }
}
​
/**
 * 创建代理对象
 */
class UserDaoInvocationHandler implements InvocationHandler {
​
    
    private Object o;
    //把创建是谁的代理对象把谁传递过来
    public UserDaoInvocationHandler(Object o){
        this.o=o;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("方法之前执行"+method.getName() + Arrays.toString(args));
        Object res = method.invoke(o, args);
        System.out.println("方法之后执行");
        return res;
    }

3.2 aop的术语

连接点:类里面的那些方法可以被增强,这些方法就被称为连接点

切入点:实际真正被增强的方法就是切入点

通知(增强):实际增强逻辑的部分就叫做通知,(增加的部分逻辑)5种通知类型:

(1)前置通知

(2)后置通知

(3)环绕通知

(4)异常通知

(5)最终通知

切面:是一个动作(把一个通知应用到切入点的过程)

<!--spring一般都是基于AspectJ实现AOP操作-->

<!--AspectJ是一个独立的aop框架,不属于spring的组成部分,一般进行组合使用进行aop操作-->

3.3 aop的实现

切入点的表达式:execution(权限修饰符,返回值类型,类的全路径,方法名称,参数列表)

<!--例子:execution(* com.wrh.spring.*(..))-->

基于xml配置文件实现:

<!--配置bean-->
<bean id="user" class="com.wrh.spring.aopxml.User"></bean>
<bean id="userProxy" class="com.wrh.spring.aopxml.UserProxy"></bean>
<!--配置aop增强-->
<aop:config >
    <!--配置切入点-->
    <aop:pointcut id="p" expression="execution(* com.wrh.spring.aopxml.User.add(..))"/>
    <!--配置切面-->
    <aop:aspect ref="userProxy">
        <aop:after method="before" pointcut-ref="p"></aop:after>
    </aop:aspect>
</aop:config>

基于注解实现:

(1)创建一个类,被增强的类

/**
 * @author wangruiheng
 */
@Component
public class Books {
    public void add(){
        System.out.println("add.................");
    }
}

(2)创建一个类,编写增强的逻辑(五种通知类型)

/**
 * @author wangruiheng
 */
@Component
@Aspect
public class BooksProxy {
​
    @Pointcut("execution(* com.wrh.spring.aop.Books.add(..))")
    public void pointcut(){}
    /**
     * 前置通知
     */
    @Before("pointcut()")
    public void before(){
        System.out.println("前置通知");
    }
​
​
    /**
     * 后置通知
     */
    @After("pointcut()")
    public void after(){
        System.out.println("后置通知");
    }
​
    /**
     * 后置通知,在将返回值返回时执行
     */
    @AfterReturning("pointcut()")
    public void afterReturning(){
        System.out.println("后置通知,在将返回值返回时执行");
    }
​
​
    /**
     * 异常通知
     */
    @AfterThrowing("pointcut()")
    public void afterThrowing(){
        System.out.println("后置异常通知");
    }
​
    /**
     * 环绕通知
     */
    @Around("pointcut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知---之前");
        proceedingJoinPoint.proceed();
        System.out.println("环绕通知---之后");
    }
}

(3)进行通知的配置

在spring中开启注解扫描

<!--开启注解扫描 -->
<context:component-scan base-package="com.wrh.spring.aop"></context:component-scan>

使用注解创建 被增强的类和增强类@Component

在增强类上加一个注解@AspectJ

  在spring配置文件中开启生成代理对象
<!--开启生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

(4) 相同切入点的提取

@Pointcut("execution(* com.wrh.spring.aop.Books.add(..))")
public void pointcut(){}

(5)多个切面时,可以通过@Order(参数【数值类型,数字越小优先级越高】)进行设置优先级

(6)全注解开发

/**
 * @author wangruiheng
 */
@Configuration//这个类是配置类
@EnableAspectJAutoProxy(proxyTargetClass = true)//开启生成代理类
@ComponentScan(basePackages = {"com.wrh.spring"})//扫描注解
public class SpringConfig {
}

4. JdbcTemplate

什么是JdbcTemplate?

JdbcTemplate是spring对jdbc的封装,对数据库的操作更加方便

4.1JdbcTemplate的配置

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <property name="url" value="jdbc:mysql:///user_db" ></property>
    <property name="username" value="root" ></property>
    <property name="password" value="tiger" ></property>
    <property name="driverClassName" value="com.mysql.jdbc.Driver" ></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
</bean>
<context:component-scan base-package="com.wrh.spring"></context:component-scan>
@Test
public void add(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean1.xml");
    UserServiceImpl userServiceImpl = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
    User user = new User();
    user.setId(2);
    user.setName("小花");
    user.setSex("女");
    userServiceImpl.add(user);
}


@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(User user) {
    String sql = "insert into users VALUES(?,?,?);";
    int update = jdbcTemplate.update(sql,user.getId(), user.getName(), user.getSex());
    System.out.println(update);
}


5. 事务管理

什么是事务?

事务式数据库操作的基本单元。逻辑上的一组操作,要么都成功,要么都失败,典型的场景:银行转账

5.1 事务的四个特性:(ACID)

  • 原子性:(过程中不可分割,要么都成功要么都失败)

  • 一致性:(操作之前和操作之后总量不变)

  • 隔离性:(多事务操作的时候彼此之前不产生影响)

  • 持久性:(事务操作完成之后数据存入数据库)

5.2 事务操作

spring事务操作的步骤

1.事务添加到service层(业务逻辑层)

2.事务分为两种:编程式和声明式事务管理

3.声明式事务管理:

(1)基于注解方式

在spring配置文件中配置事务管理器

  1. 配置事务管理器

     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
         <property name="url" value="jdbc:mysql:///user_db?useSSL=false&amp;useTimezone=true&amp;serverTimezone=GMT%2B8" ></property>
         <property name="username" value="root" ></property>
         <property name="password" value="tiger" ></property>
         <property name="driverClassName" value="com.mysql.jdbc.Driver" ></property>
     </bean>
     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
         <property name="dataSource" ref="dataSource"></property>
     </bean>
     <context:component-scan base-package="com.wrh.spring"></context:component-scan>
    <!--配置事务管理器-->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="dataSource"></property>
     </bean>
    
     <!--配置通知-->
     <tx:advice id="advice">
         <tx:attributes>
             <tx:method name="add" propagation="REQUIRED"/>
         </tx:attributes>
     </tx:advice>
    
     <!--配置切入点和切面-->
     <aop:config>
         <!--配置切入点-->
         <aop:pointcut id="pt" expression="execution(* com.wrh.spring.service.UserServiceImpl.*(..))"/>
         <!--配置切面-->
         <aop:advisor advice-ref="advice" pointcut-ref="pt"></aop:advisor>
     </aop:config>	

(2)基于xml配置文件方式

4.在spring中进行声明式事务管理,底层使用aop原理

5.3 spring事务管理api

(1)提供了一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

PlatFormTransactionManager

(2)spring配置事务

 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
     <property name="url" value="jdbc:mysql:///user_db" ></property>
     <property name="username" value="root" ></property>
     <property name="password" value="tiger" ></property>
     <property name="driverClassName" value="com.mysql.jdbc.Driver" ></property>
 </bean>
 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
     <property name="dataSource" ref="dataSource"></property>
 </bean>
 <context:component-scan base-package="com.wrh.spring"></context:component-scan>
<!--配置事务管理器-->
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource"></property>
 </bean>
 <!--开启事务注解-->
 <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

添加注解@Transactional

5.4 注解的相关属性

propagation:事务的传播行为(<!--多事务之间的调用,事务之间是如何管理的-->)

<!--REQUIRED:如果有事务在运行,当前的方法就在这个事务内运行,否则就启动一个新的事务,并在自己的事务内运行-->

<!--REQUIRED_NEW:当前的方法必须启动新的事务,并在自己的事务内运行,如果有事务运行,应该将它挂起-->

<!--SUPPORTS:如果有事务运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中-->

<!--NOT_SUPPORTE:当前的方法是不运行在事务中,如果有运行的事务,就将它挂起-->

<!--MANDATORY:当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常-->

<!--NEVER:当前的方法不应该运行在事务中,如果有运行的事务就抛出异常-->

<!--NESTED:如果有事务运行,当前方法就应该在这个事务的嵌套事务内运行,否则,就启动一个新的事务,并在它自己的事务内运行-->

ioslation:事务的隔离级别(事务有特性称为隔离性,多事务操作之间不会产生影响,不考虑事务的隔离性会产生很多的问题)

脏读:一个未提交的事务读取到一个未提交的数据

不可重复读:一个未提交的事务读取到一个已提交事务修改的数据

幻读:一个未提交的事务读取到一个已提交事务添加的数据

timeout:超时时间(单位秒,默认-1,不超时)

readOnly:是否只读(默认是false。可以查询也可以修改,开启之后只内查询不能修改)

rollbackFor:回滚(出现哪些异常类型回滚)

norollbackFor:不回滚(出现哪些异常类型不进行回滚)

5.5 全注解开发

@Configuration //配置类

@ComponentScan //组建扫描

@EnableTransactionManagement //开启事务

@Bean //创建bean

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发型决定高度

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值