Spring5

IOC

IOC 容器原理分析

https://javadoop.com/post/spring-ioc点我

bean管理

  • spring中有两种类型bean,一种是普通bean,一种是工厂bean
  • 普通bean就是在配置文件中定义什么类型的,getBean的时候就是什么类型
  • 工厂bean是定义的什么类型,返回的不一定是配置文件中定义的类型:
    • 让类实现FactoryBean接口,并实现方法,在方法中定义要返回的bean类型
    public class FactoryBeanDemo implements FactoryBean {
        @Override
        public Object getObject() throws Exception {
            Emp emp = new Emp();
            return emp;
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    
        @Override
        public boolean isSingleton() {
            return false;
        }
    }
    

bean的作用域

  • spring中默认创建的bean是单例的,即配置文件中scope属性为singleton,在加载配置文件的时候创建对象
  • scope属性设置为prototype,则创建出来的对象是多实例的,在getBean的时候才创建对象

bean的生命周期

  • 通过构造器创建bean实例
  • 为bean的属性赋值和引用其他的bean
  • 调用bean的初始化方法(需要配置)
  • 获取需要的bean对象
  • 容器关闭的时候,调用bean的销毁方法(需要配置)
    在这里插入图片描述
    在这里插入图片描述

加上bean的后置处理器,bean的生命周期由7步

会给所有的bean对象的都加上后置处理器

  • 通过构造器创建bean实例
  • 为bean的属性赋值和引用其他的bean
  • 把bean的实例传递给后置处理器方法postProcessBeforeInitialization
  • 调用bean的初始化方法(需要配置)
  • 把bean的实例传递给后置处理器方法
  • 获取需要的bean对象postProcessAfterInitialization
  • 容器关闭的时候,调用bean的销毁方法(需要配置)
    运行结果:
    在这里插入图片描述在这里插入图片描述

XML方式自动装配(很少用到)

  • 通过在bean标签里面加入autowire属性实现自动装配
  • 1、byName,通过名字实现
  • 2、byType,通过属性类型实现

IOC操作bean,为bean属性引入外部属性文件

  • 加入<context:property-placeholder location="classpath:"></context:property-placeholder>
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClass}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.username}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>

IOC操作bean管理

  • 注解:代码的特殊标记

  • 使用注解可以标注在类、方法、属性上

  • 使用注解的目的就是简化xml配置

  • spring针对bean管理中创建对象提供注解

    • Component,标注在组件上
    • Controller,通常标注在web层
    • Service,通常标注在业务处理层
    • Repository,通常标注在DAO层

    以上四个注解作用都是一样

  • 在xml配置文件中添加
    <context:component-scan base-package=" "></context:component-scan>

  • 在对应的类上加入以上注解就可以将创建对象交由spring容器管理,注解属性value默认值是类名首字母 小写,相当于配置文件中的id属性

    <!--只扫描包含 Controller注解的类-->
        <context:component-scan base-package="com.feng" use-default-filters="false">
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    
    <!--不扫描包含Controller的-->
        <context:component-scan base-package="com.feng">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    
  • 基于注解方式实现属性注入

    • 1、@Autowire,根据类型注入
    • 2、@Qualifier,根据属性名称注入,要与 Autowire配合使用
    	@Autowired
        @Qualifier(value = "userDaoImpl")
        private UserDao userDao;
    
    • 3、@Resource,属性名称,类型都可以
    • 4、@Value,注入普通属性

完全注解开发

  • 创建SpringConfig的spring配置类,在该类上加上@Configuration和@ComponentScan(basePackages = “”)

AOP

1、定义

  • 利用aop可以将业务逻辑的各个部分进行分离,降低耦合性,提高可重用性,提高开发效率
  • 不修改源代码,实现添加新功能

2、原理

  • 有接口,使用jdk动态代理
    • 添加接口实现类代理对象
  • 没有接口,使用CGLIB动态代理
    • 创建当前类的子类的代理对象,增强类的方法
  • AOP,jdk动态代理
    • 使用Proxy类里面的方法创建代理对象
    • newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
    • 第一个参数,类加载器
    • 第二个参数,增强方法所实现的类,该类实现的接口,可以有多个接口
    • 第三个参数,实现这个接口InvocationHandler,创建代理对象,写增强的部分

3、AOP术语

  • 1、连接点:类里面哪些方法可以被增强,这些方法可以称为连接点
  • 2、切入点:实际被增强的方法,称为切入点
  • 3、通知(增强):实际增强的逻辑部分称为通知或增强
    • 前置通知
    • 后置通知
    • 环绕通知
    • 异常通知
    • 最终通知
  • 4、切面:把通知应用到切入点的过程

4、AOP操作

  • 1、spring框架一般都基于AspectJ实现AOP 操作
    • aop不是spring的组成部分,一般把AspectJ和spring一起使用,进行AOP操作
  • 2、基于xml实现和基于注解实现
  • 3、切入点表达式
    • 作用:知道对哪个类的哪个方法进行增强
    • 语法结构:execution([权限修饰符] [返回值类型] [类全路径] [方法名称] (参数列表))
    • 例:execution(* com.feng.dao.Book.*(…))表示对Book类下面的所有方法进行增强
  • 4、引入依赖后,在代理类上面加入注解@Aspect,在xml配置文件中添加aop:aspectj-autoproxy></aop:aspectj-autoproxy>标签开启Aspect生成代理对象
  • 例:
@Component
@Aspect
public class UserProxy {

    @Before(value = "execution(* com.feng.bean.User.*(..))")
    public void before() {
        System.out.println("前置通知Before....");
    }

    //异常也会执行
    @After(value = "execution(* com.feng.bean.User.*(..))")
    public void after() {
        System.out.println("最终通知After....");
    }

    //有返回值之后才执行,异常不执行
    @AfterReturning(value = "execution(* com.feng.bean.User.*(..))")
    public void afterReturn() {
        System.out.println("后置通知(返回通知)AfterReturning..");
    }

    //异常通知
    @AfterThrowing(value = "execution(* com.feng.bean.User.*(..))")
    public void afterThrowing() {
        System.out.println("异常通知,afterThrowing。。。");
    }

    //环绕通知,在被代理类的方法前后都会执行
    @Around(value = "execution(* com.feng.bean.User.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知前,around....");
        joinPoint.proceed();
        System.out.println("环绕通知后,around。。。");
    }
}
  • 加入异常:
  • 在这里插入图片描述
  • 没有异常
  • 在这里插入图片描述
  • 相同的切入点抽取
    利用@Pointcut(value=“切入点表达式”)
  • 设置增强类优先级
    在增强类的方法上添加@Order注解,值为int类型,值越小优先级越高
  • xml配置aop
<!--被代理的类-->
    <bean class="com.feng.aopxml.Book" id="book"></bean>
    <!--代理类-->
    <bean class="com.feng.aopxml.BookProxy" id="bookProxy"></bean>
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.feng.aopxml.Book.*(..))"/>
        <!--定义切面:把通知应用到切入点的过程-->
        <aop:aspect ref="bookProxy">
            <!-- 前置通知-->
            <aop:before method="before" pointcut-ref="pointcut"></aop:before>
        </aop:aspect>
    </aop:config>
  • 全注解方式,只需要添加spring配置类,如下:
@Configuration
@ComponentScan(value = "com.feng")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}

注意:使用xml方式时,加载配置文件是用new ClassPathXmlApplicationContext("beans2.xml")
改为注解方式应该使用new AnnotationConfigApplicationContext(ConfigAop.class);

5、spring aop和AspectJ AOP有什么区别

  • 1、springaop是运行时增强,AspectJ是编译时增强
  • 2、springaop是基于代理,而AspectJ是基于字节码操作
  • 3、切面多,使用AspectJ,因为比spring快很多

JDBC Template

1、概念

  • spring框架对jdbc进行了封装,使用jdbc Template方便了对数据库进行操作

2、需要的引入的依赖

<!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--数据库连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--对jdbc的封装-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <!--为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <!--Spring 的ORM模块提供对常用的ORM框架的管理和辅助支持-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>

配置数据库连接池

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost/yonghedb"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

配置JDBCTemplate,注入数据源对象

<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

事务

概念

  • 事务是数据库最基本的单元,逻辑上一组操作,要么都成功,要么都失败

特性

  • 1、原子性:一组操作要么都成功,一个失败都失败
  • 2、一致性:事务开始之前和事务结束以后,数据库的完整性约束没有被破坏
  • 3、隔离性:多个事务之间相互隔离,互不干扰
  • 3、永久性:该事务对数据的所有更改将永久保存在数据库,不会被回滚

实现

  • 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
  • 开启事务注解
  • 在xml配置上添加命名空间
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation:http://www.springframework.org/schema/tx http://www.springframework.org/schema/beans/spring-tx.xsd
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
  • 在需要添加事务的类,添加注解@Transaction也可以添加在方法上
    如果在类上,表示该类里面的所有的方法,添加事务
    如果在方法上,表示仅该方法添加事务

声明式事务管理参数配置

  • @Transaction这个注解里面可以配置相关参数
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    Propagation propagation() default Propagation.REQUIRED;

    Isolation isolation() default Isolation.DEFAULT;

    int timeout() default -1;

    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}
posted @ 2022-11-11 20:47  小匠i  阅读(36)  评论(0)    收藏  举报