Spring

Spring



提示:以下是本篇文章正文内容,下面案例可供参考

一、控制反转IOC

1.概念了解

1.控制反转(IoC,Inversion of Control),是一个概念,是一种思想。指将传统上由程序代
码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。
2.依赖注入:DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行
完成。

2.第一个spring程序

I.spring依赖引入

	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

II.定义实体类

在这里插入图片描述

III.创建Spring配置文件

在 src/main/resources/目录现创建一个 xml 文件,文件名可以随意,但 Spring 建议的名
称为 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"> <!--spring-beans.xsd 是约束文件 控制本配置文件可以出现的标签和属性-->

    <!-- 声明bean 告诉spring创建对象
         id: spring所创建对象的标识
         class: 所需创建对象的类型,类的全限定名称

         spring完成了  SomeService service = new SomeServiceImpl();
         spring将出创建好的对象放入spring专门放置对象的Map中
            springMap.put(bean的id,对象)
            该bean创建可理解为: springMap.put(someService,new SomeServiceImpl())
          -->
    <bean id="someService" class="chong.jiang.service.impl.SomeServiceImpl" />
</beans>

IIII.ApplicationContext的获取及常用API

 @Test
    public void testAcApi(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        System.out.println("容器中对象数量:" + ac.getBeanDefinitionCount());
        for(String name : ac.getBeanDefinitionNames()){
            System.out.println(name);
        }
        System.out.println((new SimpleDateFormat(("yy/MM/dd HH:mm")).format(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24))));
    }

获取时对象时注意:
在这里插入图片描述

IIIII.使用spring创建的对象

@Test
    public void testSpringCreateBean(){
        //1.指定spring配置文件
        String config = "applicationContext.xml";
        //2.创建表示spring容器的对象ApplicationContext
                                //ClassPathXmlApplicationContext类路径下加载配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //3.从容器对象中获取对象,并转成对应的类型
        SomeService someService = (SomeService)ac.getBean("someService");
        someService.doSome();
    }

3.基于xml的DI

I.注入分类

a.set注入
	<bean id="student" class="chong.jiang.domain.bean.Student">
	        <property name="name" value="小江" />     <!--遇到name的值为xxx,就会调用xxxSet()方法,不管是否存在该属性,是否赋值-->
	        <property name="age" value="18" />
	        <property name="school" ref="school" />		<!--使用ref对引用类型赋值-->
	</bean>
	<bean id="school" class="chong.jiang.domain.bean.School">
	        <property name="name" value="工程学院" />
	        <property name="address" value="重庆" />
	</bean>
b.构造注入
	 <bean id="myStudent" class="chong.jiang.domain.bean.Student">
        <constructor-arg index="0" value="张三" />
        <constructor-arg value="20" />   <!--默认为index="1"-->
        <constructor-arg name="school" ref="school" />
    </bean>

II.引用类型的自动注入

a.byName(按名称注入)
赋予与属性名相同的id标识的bean对象

在这里插入图片描述

b.byType(按类型注入)
赋予与该属性同源的bean对象

在这里插入图片描述

III.配置多个spring配置文件

<?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"> <!--spring-beans.xsd 是约束文件 控制本配置文件可以出现的标签和属性-->
<!--   spring主配置文件  加载其他配置文件 resource="classpath:配置文件的类路径" 可以用通配符“*” 注意:不能加载主配置文件,加载时配置文件需要放在一个目录中-->
    <import resource="classpath:spring-school.xml"/>
    <import resource="classpath:spring-student.xml"/>

</beans>

3.基于注解的DI

I.使用注解创建bean

@spring中和@Component功能一致,创建对象的注解还有:
1.@Repository(用在持久层类的上面) : 放在dao的实现类上面
        表示创建访问数据库的dao对象
2.@Service(用在业务层类的上面) : 放在service的实现类上面,
        表示创建业务处理、事务处理的service对象
3.@Controller(用在控制器的上面) : 放在控制类的上面,创建控制器对象
        表示创建接受用户提交参数、显示请求结果的控制器对象
a.在创建的类上使用@Component()注解

在这里插入图片描述

b.在 Spring 配置文件中配置组件扫描器
	<!--声明组件扫描器(component-scan),组件就是java对象
        base-package:指定注解在项目中的包名
        spring会扫描遍历base-package指定的包及其子包中的所有类,找到类中的注解,并按照注解的功能创建对象或这给对象赋值
    -->
    <context:component-scan base-package="chong.jiang.domain"/>
c.使用创建的对象

在这里插入图片描述

II.配置多个包的扫描器

请添加图片描述

III.属性注入

a.简单类型属性赋值
@Value  简单类型属性赋值
位置:  1.在属性定义上赋值,无需set方法,建议使用
       2. 在set方法上面使用 

使用:
在这里插入图片描述

b.引用类型属性赋值
$1.使用Autowired(required=true)注解
@Autowired(默认使用byType自动注入)  引用类型属性自动赋值    支持byName,byType  
    位置:  1.在属性定义上赋值,无需set方法,建议使用
          2. 在set方法上面使用
    属性:required ,表示属性赋值失败后是否报错,并停止运行,默认为true
    							为假时,属性赋值失败后为null
    
若要使用byName的方式注入,需要在属性加入@Autowired之后
    多加一个@Qualifier(value="bean的id值")

在这里插入图片描述

$2.使用Resource注解()
@Resource( 默认使用byName自动注入,如果赋值失败,再使用ByType)  引用类型属性自动赋值    支持byName,byType 来自于JDK中
位置:  1.在属性定义上赋值,无需set方法,建议使用
      2. 在set方法上面使用

当只是用ByName方式时,再注解中使用name属性,指定bean对象的id值
在这里插入图片描述

IIII.属性配置文件与注解注入的配合使用

a.加载配置文件

在这里插入图片描述

b.使用${}占位符

在这里插入图片描述

IIIII.xml注入与注解注入的选择

代码易常改动时,使用xml注入
代码不常改动时,使用注解注入(使用较多)

二、面向AOP编程

AOP 底层,就是采用动态代理模式实现的。

1. AOP编程术语

I.切面(Aspect)

切面泛指交叉业务逻辑,事务处理、日志处理就可以理解为切面,实际就是对主业务逻辑的一种增强。

II.连接点(JoinPoint)

连接点指可以被切面织入的具体方法。final修饰的方法不能做连接点

III. 切入点(Pointcut)

一个或多个连接点的集合。

IIII. 目标对象(Target)

将要被增强的主业务逻辑的类的对象

IIIII. 通知(Advice)

知表示切面的执行时间,Advice 也叫增强。

2. AspectJ对AOP的实现

I.AspectJ 的通知类型

在这里插入图片描述

II.AspectJ 的切入点表达式

表达式原型:

	execution(modifiers-pattern? ret-type-pattern 
	declaring-type-pattern?name-pattern(param-pattern)
	 throws-pattern?)

解释:
在这里插入图片描述
理解为:
在这里插入图片描述
表达式常用匹配符:
在这里插入图片描述

3. AspectJ的使用

I.引入依赖

	<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

II.基本实现

a.定义接口与实现类
//接口
public interface SomeService {
    void doSome(String name,Integer age);
}

//实现类
public class SomeServiceImpl implements SomeService{
    @Override
    public void doSome(String name, Integer age) {
        System.out.println("=====目标方法doSome()执行======");
    }
}
b.定义切面类
/*
@Aspect: 表示当前类表示切面类,用来给业务方法增加功能的类
 */
@Aspect
public class MyAspect {
    /*
    定义实现切面功能的方法
     */
    /*
    @Before : 前置通知注解
    属性: value,是切入点表达式,表示切面功能的执行位置
    在目标方法执行之前执行
     */
            //方法权限修饰符   返回值类型   方法声明(参数类型,参数类型...)    无异常
    @Before("execution(public void chong.jiang.ba01.SomeServiceImpl.doSome(String, Integer))")
    public void myBefore(){
        System.out.println("切面功能(前置通知):在目标方法执行之前输出执行时间:" + new Date());
    }
}
c.声明目标对象与切面类对象

在这里插入图片描述

d.注册 AspectJ 的自动代理

在这里插入图片描述

e.使用目标对象的id获取成功的代理对象

在这里插入图片描述

III. 多种通知方法的使用

a.@Before 前置通知
public void myBefore(JoinPoint joinPoint){
        /*
        JoinPoint要加入切面功能的业务方法 由框架赋值,必须放在参数列表的第一位
        可以在通知方法中获取方法执行时发信息,如方法名称,方法的实参
         */
        //获取方法完整定义
        System.out.println("方法签名(定义)=" + joinPoint.getSignature());
        System.out.println("方法的名称=" + joinPoint.getSignature().getName());
        //获取方法实参
        Object[] args = joinPoint.getArgs();
        for(Object arg : args){
            System.out.println("参数=" + arg);
        }
        System.out.println("切面功能(前置通知):在目标方法执行之前输出执行时间:" + new Date());
    }

执行结果:
在这里插入图片描述

b.@AfterReturning 后置通知

在这里插入图片描述
执行结果:
在这里插入图片描述

c.@Around 环绕通知

在这里插入图片描述
结果
在这里插入图片描述

d.@AfterThrowing 异常通知

在这里插入图片描述

e.@After 最终通知

在这里插入图片描述

f. @Pointcut 定义切入点

在这里插入图片描述

f. JDK动态代理与cglib动态代理自动切换
当代理的类没有实现接口时,spring自动使用cglib的动态代理(继承方式)

有实现接口时:
在这里插入图片描述
没有实现接口的代理:
在这里插入图片描述
有接口实现时,使用cglib代理
在这里插入图片描述

三、Spring集成Mybatis

spring配置文件:创建druid,sqlsessionfactory,dao对象

 <!--把数据库的配置信息写在独立文件中
    加载属性文件,也就是占位符的本地存储
    -->
    <context:property-placeholder location="classpath:jdbc.properties" />
    <!--连接池对象-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="${jdbc.maxActive}" />
    </bean>

    <!--   用mybatis提供的SqlSessionFactoryBean类,创建factory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--给factory配置连接池-->
        <property name="dataSource" ref="dataSource"/>
        <!--mybatis的主配置文件
        configLocation 类型为Resource 用于读取配置文件
        -->
        <property name="configLocation" value="classpath:mybatis.xml" />
    </bean>

    <!--创建dao对象,使用SqlSession的getMapper(StudentDao.class)
    MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    			<!--属性sqlSessionFactoryBeanName的类型是String类型,所以这里用value-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--指定包名,包名是dao接口所在的包名
        MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
        一次getMapper()方法,得到的每个dao对象都放入spring的容器中,多个包用","分隔
        dao对象的默认名称是 接口名首字母小写
        -->
        <property name="basePackage" value="chong.jiang.dao" />
    </bean>

    <bean id="studentService" class="chong.jiang.service.impl.StudentServiceImpl" >
        <property name="studentDao" ref="studentDao"/>
    </bean>

四、Spring统一事务管理

1.使用 Spring 的事务注解管理事务(中小型项目)

I.事务管理器接口(重点)

PlatformTransactionManager 接口有两个常用的实现类:
DataSourceTransactionManager:使用 JDBC 或 MyBatis 进行数据库操作时使用。
HibernateTransactionManager:使用 Hibernate 进行持久化数据时使用。

II.spring事务回滚方式

Spring 事务的默认回滚方式是:发生运行时异常和 error 时回滚,发生受查(编译)异常时提交。

III.事务定义接口

a.事务隔离级别
MySql 的默认为 REPEATABLE_READ; Oracle默认为 READ_COMMITTED。
b.事务传播行为
PROPAGATION_REQUIRED		指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务。也是 Spring 默认的事务传播行为。
PROPAGATION_REQUIRES_NEW	指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。如执行查询方法时
PROPAGATION_SUPPORTS	总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。
c.事务超时

IIII.开启spring事务处理的spring配置

	<!--    1.声明事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--指定数据源-->
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!--  2.开启事务注解驱动,告诉spring使用注解管理事务,创建代理对象
            transaction-manager: 事务管理器对象
             -->
    <tx:annotation-driven transaction-manager="transactionManager" />

IIIII.注解使用

在这里插入图片描述

2.使用 AspectJ 的 AOP 配置管理事务(大型项目)

I.配置到spring.xml中的配置

<!--    1.声明事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--指定数据源-->
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!--  2.声明业务方法的事务属性(隔离级别,传播行为,超时时间)
                id:自定义名称,表示该配置的标识
    -->
   <tx:advice id="myAdvice" transaction-manager="transactionManager">
       <!--配置事务属性-->
        <tx:attributes>
            <!---给具体的方法配置事务属性-->
            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                       rollback-for="java.lang.NullPointerException,chong.jiang.excep.NotEnoughException"/>
        </tx:attributes>
   </tx:advice>
    <aop:config>
        <!--
        配置切入点表达式,指定那些包中的类要使用事务
        id:该个切入点表达式的标识
        expression:切入点表达式,只当让aspectJ为那些类创建代理对象
        -->
        <aop:pointcut id="servicePt" expression="execution(* *..Service..*.*(..))"/>
        <!--配置增强器:advice和pointcut
            配置advice与pointcut的关联
        -->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt" />
    </aop:config>

五、Spring与web

使用监听器创建spring容器

I.在maven中加入依赖

 <!-- 为了使用监听器对象    -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

II.注册监听器 ContextLoaderListener

在 web.xml 中注册该监听器

<!--注册监听器ContextLoaderListener
        监听器对象被创建后,会读取/WEB-INF/applicationContext.xml
        为了创建ApplicationConText对象,需要加载配置文件,spring默认加载路径为/WEB-INF/applicationContext.xml
    -->
    <context-param>
    	<!--从监听器 ContextLoaderListener 的父类 ContextLoader 的源码中可以看到其要读取的配
置文件位置参数名称 contextConfigLocation。-->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
   <listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>

Spring 为该监听器接口定义了一个实现类 ContextLoaderListener,完成了两个很重要的工作:创建容器对象,并将容器对象放入到了 ServletContext 的空间中。

III.获取Spring 容器对象

a.直接从 ServletContext 中获取
      ApplicationContext ctx = null;
      //从对监听器 ContextLoaderListener 的源码分析可知,容器对象在 ServletContext 的中存放的 key 为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。
      String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
      Object attr = getServletContext().getAttribute(key);
      if(attr != null){
          ctx = (ApplicationContext)attr;
      }
b.通过 WebApplicationContextUtils 获取
//使用框架方法获取容器对象
ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值