spring笔记

一、使用spring框架的步骤

  1. 加入依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    
  2. 创建类:接口、实现类、没有接口的类

  3. 创建spring的配置文件,使用声明对象

  4. 创建使用容器中的对象,通过ApplicationContext接口和它的实现类ClassPathXmlApplicationContext的方法getBean()

二、基于注解的di

  1. 加入maven的依赖 spring-context,在你加入spring-context的同时,间接加入spring-aop的依赖。使用注解必须使用spring-aop依赖
  2. 在类中加入spring的注解(多个不同功能的注解)
  3. 在spring的配置文件中,加入一个组件扫描的标签,说明注解在你的项目中的位置。

三、注解

  1. @Component:创建对象的,等同于的功能

    。属性:value就是对象的名称,也就是bean的id值

    ​ value的值是唯一的,创建的对象在整个spring的容器中

    。位置:在类的上面

    @Component(value = “myStudent”)等同于

    spring中和@component功能一致,创建对象的注解还有:

    2.@Repository (用在持久层类的上面):放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库的。

3.@Service(用在业务层类的上面):放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务等功能的.

4.@Controller(用在控制器的上面)∶放在控制器(处理器)类的上面,创建控制器对象的,
控制器对象,能够接受用户提交的参数,显示请求的处理结果。

以上三个注解的使用语法和@component一样的。都能创建对象,但是这三个注解还有额外的功能。
@Repository , @Service , @controller是给项目的对象分层的。

四、指定多个包的扫描方式

第一种方式:使用多次组件扫描器,指定不同的包
<context:component-scan base-package="com.bjpowernode.bao1"/>
<context:comporant-scan base-package="com.bjpowernode.ba02"/>

第二种方式:使用分隔符(;或,)分隔多个包名
<context:component-scan base-package="com.bjpowernode.ba01;com.bjpowernode.bao2”/>

第三种方式:指定父包
<context:component-scan base-package="com.bjpowernode”/>

五、自动注入

/*引用类型
@Autowired:spring框架提供的注解,实现引用类型的赋值。
* spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,byType

@Autowired:默认使用的是bytype自动注入。
属性:required,是一个boolean类型的,默认true
required=true :表示引用类型赋值失败,程序报错,并终止执行。
required=fals:引用类型如果赋值失败,程序正常执行,引用类型是null

*位置: 1)在属性定义的上面,无需set方法,推荐使用
	  2)在set方法的上面
*如果要使用byName方式,需要做的是:
*	1.在属性上面加入@Autowired
	2.在属性上面加入@Qualifier(value="bean的id"):表示使用指定名称的bean完成赋值。
*/


/*如果要使用byName方式,需要做的是:
*1.在属性上面加入@Autowired
*2.在属性上面加入@Qualifier(value="bean的id"):表示使用指定名称的bean完成赋值。
*/
@Qualifier("myschool")
@Autowired 
private school school;
public student({
system.out.println("==student无参数构造方法===");
    
    
@Resource
/*引用类型
来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类
@Resource:
使用的也是自动注入原理,支持byName ,byType .默认是byName

位置:1.在属性定义的上面,无需set方法,推荐使用。
	2.在set方法的上面
    默认是byName:先使用byName自动注入,如果byName赋值失败,再使用byType
*/

六、aop

aop的实现
aop是一个规范,是动态的一个规范化,一个标准

aop的技术实现框架:
1.spring:spring在内部实现了aop规范,能做aop的工作。spring主要在事务处理时使用aop.我们项目开发中很少使用spring的aop实现。因为spring的aop比较笨重。

​ 2.aspectJ:一个开源的专门做aop的框架。spring框架中集成了aspectj框架,通过spring就能使用aspectj的功能。

​ aspectJ框架实现aop有两种方式:
​ 1.使更用xml的配置文件:配置全局事务
​ 2.使用注解,我们在项目中要做aop功能,一般都使用注解,aspectj有5个注解。

七、AspectJ框架的使用

1、切面的执行时间,这个执行时间在规范中叫做Advice (通知,增强)

在aspectj框架中使用注解表示的。也可以使用xml配置文件中的标签

  1. @Before

  2. @AfterReturning

  3. @Around

  4. @AfterThrowing

  5. @After

2、AspectJ 的切入点表达式
  • execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(parampattern)
    throws-pattern?)

  • execution(访问权限 方法返回值 方法声明(参数) 异常类型)

  • 符号意义
    *0至多个任意字符
    用在方法参数中,表示任意多个参数用在包名后,表示当前包及其子包路径
    +用在类名后,表示当前类及其子类用在接口后,表示当前接口及其实现类

    举例:

    execution(public * (…))
    指定切入点为:任意公共方法。
    execution(
    set*(…))
    指定切入点为:任何一个以“set”开始的方法。
    execution(* com.xyz.service..(…))
    指定切入点为:定义在 service 包里的任意类的任意方法。
    execution(* com.xyz.service….(…))
    指定切入点为:定义在 service 包或者子包里的任意类的任意方法。“…”出现在类名中时,后
    面必须跟“”,表示包、子包下的所有类。
    execution(
    …service..*(…))
    指定所有包下的 serivce 子包下所有类(接口)中所有方法为切入点

3、使用aspectj实现aop的基本步骤:

​ 1.新建maven项目
​ 2.加入依赖
​ 1 ) spring依赖
​ 2 ) aspectj依赖

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

​ 3 ) junit单元测试
​ 3.创建目标类:接口和他的实现类。要做的是给类中的方法增加功能
​ 4.创建切面类:普通类
​ 1)在类的上面加入@Aspect
​ 2)在类中定义方法,方法就是切面要执行的功能代码
​ 在方法的上面加入aspectj中的通知注解,例如@Before有需要指定切入点表达式execution()
​ 5.创建spring的配置文件:声明对象,把对象交给容器统一管理 声明对象你可以使用注解或者xml配置文件
​ 1)声明目标对象
​ 2)声明切面类对象
​ 3 )声明aspectj框架中的自动代理生成器标签。
​ 自动代理生成器:用来完成代理对象的自动创建功能的。

4、AspectJ基于注解的AOP实现

1.1)定义业务接口与实现类----@Beforce前置通知

public interface SomeService{
    void doSome(String name,int age)
}

public class SomeServiceImpl implemenets SomeService{
    public void doSome(String name,int age){
        System.out.println("执行了业务doSome方法")
    }
}

2)定义切面类

类中定义了若干普通方法,将作为不同的通知方法,用来增强功能

@Aspecct
public class MyAspect{
    /*
      @Beforce:前置通知
      	属性:value 切入点表达式,表示切面执行的位置
      	位置:方法的定义上面
    */
    @Beforce
    public void myBeforce(){
        //就是切面代码的功能,例如日志的输出,事务的处理
        System.out.println("前置通知:在目标方法之前先执行,例如输出日志")
    }
}

3)声明目标对象切面类对象

<!--声明目标类对象-->
<bean id="someServiceTarget" class="com.hxc.SomeServiceImpl"></bean>

<!--声明切面类对象-->
<bean id="myAspect" class="com.hxc.MyAspect"></bean>

4)注册Aspect的自动代理

<!--声明目标类对象-->
<bean id="someServiceTarget" class="com.hxc.SomeServiceImpl"></bean>

<!--声明切面类对象-->
<bean id="myAspect" class="com.hxc.MyAspect"></bean>

<!--声明自动代理生成器,创建代理-->
<aop:aspect-autoproxy/>

5)测试类中使用目标对象的id

public void test(){
    
    String configLocation = "com/hxc/applicationContext.xml";
    ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
    
    //从spring容器中获取目标对象,目标就是经过aspect修改后的代理对象
    SomeService proxy = (SomeService)ctx.getBean("someServiceTarget");
    
    //通过代理执行业务方法,实现功能增强
    proxy.doSome("zs",20);
}

2.1)@Around环绕通知

  • 接口增加方法
public interface SomeService{
    void doSome(String name,int age);
    String doOther(String name,int age);
    String doFirst(String name,int age);
}
  • 接口方法的实现
@Override
public String doFirst(String name,int age){
    System.out.println("执行了业务方法doFirst");
    return "doFirst";
}
  • 定义切面
@Around(value="execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAroud(ProceedingJoinPoint pjp) throws Throwable{
    
    Object obj = null;
    //增强功能
    System.out.println("环绕通知:在目标方法执行之前的,例如输出日志");
    //执行目标方法的调用,等同于method.invoke(target,args)
    obj = pjp.proceed();
     //增强功能
    System.out.println("环绕通知:在目标方法之后执行的,例如处理事务");
    return obj;
}

3.1)@AfterReturning后置通知

  • 接口增加方法
public interface SomeService{
    void doSome(String name,int age);
    String doOther(String name,int age)        
}
  • 实现方法
@Override
public String doOther(String name,int age){
    System.out.println("执行了业务方法doOther");
    return "abcd";
}
  • 定义切面
@AfterReturning(value="execution(* *..SomeServiceImpl.doOther(..))",returning="result")
public void myAfterReturning(Object result){
    //修改目标方法的执行结果
    if(result != null){
        String s = (String)result;
        result = s.toUpperCase();
    }
    System.out.println("后置通知:在目标方法之后执行的功能增强,例如执行事务处理")
}

4.1)@Pointcut定义切入点

​ 当较多的通知增强方法使用相同的 execution 切入点表达式时,编写、维护均较为麻烦。
AspectJ 提供了@Pointcut 注解,用于定义 execution 切入点表达式。
​ 其用法是,将@Pointcut 注解在一个方法之上,以后所有的 execution 的 value 属性值均
可使用该方法名作为切入点。代表的就是@Pointcut 定义的切入点。这个使用@Pointcut 注解
的方法一般使用 private 的标识方法,即没有实际作用的方法。

@Afer(value="mypt()")
public void myAfter(){
    System.out.println("最终通知:总是会被执行的方法")
}
/*
  @Pointcut:用来定义和管理切面点。简化切入点的定义
*/
@Pointcut(value="* *..SomeServiceImpl.doThird(..)")
private void mypt(){
    //无需代码
}

八、spring与mybatis整合

一、步骤:

1.新建maven项目
2.加人maven的依赖
1 ) spring依赖
2 ) mybatis依赖
3 ) mysql驱动
4 ) spring的事务的依赖
5 ) mybatis和spring集成的依赖: mybatis官方体用的,用来在spring项目中创建mybatis的sqlSesissonFactory , dao对象的
3.创建实体类
4.创建dao接口和mapper文件
5.创建mybatis主配置文件

6.创建service接口和实现类,属性是dao。
7.创建spring的配置文件:声明mybatis的对象交给spring创建
1)数据源
2 ) sqlsessionFactory
3 ) Dao对象
4)声明自定义的service
8.创建测试类,获取service对象,通过service调用dao完成数据库的访间

<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
</dependency>
<!--spring核心IOC-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>
<!--做spring事务-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>
<!--mybatis依赖-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
</dependency>
<!--mybatis和spring集成的依赖-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.1</version>
</dependency>
<!--mybatis驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.9</version>
</dependency>
<!--数据库连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.12</version>
</dependency>

<!--插件:-->
<build>
	<resources>
		<resource>
			<directory>src/main/java</directory><!--所在的目录-->
			<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
				<include>**/*.properties</include>
				<include>**/*.xml</include>
			</includes>
			<filtering>false</filtering>
        </resource>
        </resources>
    
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
				  <source>1.8</source>
				  <target>1.8</target>
				</configuration>
			</plugin>
       </plugins>
</build>
二、spring配置
<!--声明数据源DataSource ,作用是连接数据库-->
        <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
        init-method="init" destroy-method="close">
            <!--set注入给DruidDataSource提供连接数据库信息-->
            <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
            <property name="maxActive" value="20"/>
        </bean>

        <!--声明的是mybatis提供的SqlSessionFactoryBean类,这个类内部创建SqlSessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--set注入 把数据库连接池付给datasource属性-->
            <property name="dataSource" ref="myDataSource"/>

            <!--mybatis主配置文件的位置
                configLocation属性是Resource类型,读取配置文件
                它的赋值,使用value,指定文件的路径,使用classpath:表示文件的位置
            -->

            <property name="configLocation" value="classpath:mybatis-config.xml"/>
        </bean>

        <!--创建dao对象,使用sqlSession的getMapper(StudentDao.class)
            MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象
        -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!--指定sqlSessionFactory对象的id-->
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>

            <!--
               指定包名,包名是dao接口所在的包名
               MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行一次
               getMapper()方法,得到每个接口的dao对象
               创建好dao对象放入到spring的容器中
            -->
            <property name="basePackage" value="com.hxc.dao"/>
        </bean>

九、事务

事务原本是数据库中的概念,在 Dao 层。但一般情况下,需要将事务提升到业务层,
即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。
在 Spring 中通常可以通过以下两种方式来实现对事务的管理:
(1)使用 Spring 的事务注解管理事务
(2)使用 AspectJ 的 AOP 配置管理事务

1、定义了五个事务隔离级别常量

这些常量均是以 ISOLATION_开头。即形如 ISOLATION_XXX。
➢ DEFAULT:采用 DB 默认的事务隔离级别。MySql 的默认为 REPEATABLE_READ; Oracle
默认为 READ_COMMITTED。
➢ READ_UNCOMMITTED:读未提交。未解决任何并发问题。
➢ READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。
➢ REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读
➢ SERIALIZABLE:串行化。不存在并发问题。

2、定义了七个事务传播行为

所谓事务传播行为是指,处于不同事务中的方法在相互调用时,执行期间事务的维护情
况。如,A 事务中的方法 doSome()调用 B 事务中的方法 doOther(),在调用执行期间事务的
维护情况,就称为事务传播行为。事务传播行为是加在方法上的。
事务传播行为常量都是以 PROPAGATION_ 开头,形如 PROPAGATION_XXX。
PROPAGATION_REQUIRED
PROPAGATION_REQUIRES_NEW
PROPAGATION_SUPPORTS

==============================以上三个需要掌握

PROPAGATION_MANDATORY
PROPAGATION_NESTEDPROPAGATION_NEVER
PROPAGATION_NOT_SUPPORTED

3、使用spring的事务注解管理事务

通过@Transactional 注解方式,可将事务织入到相应 public 方法中,实现事务管理。

  • isolation:用于设置事务的隔离级别。默认值为isolation.DEFAULT
  • readOnly:用于设置该方法对数据库的操作是否是只读的。默认值为false
  • timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为 int,默认值为
    -1,即没有时限。
  • rollbackFor:指定需要回滚的异常类。类型为 Class[],默认值为空数组。
  • rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。
  • noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。
  • noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],默认值为空
    数组。

需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非 public
方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该
方法中。因为 Spring 会忽略掉所有非 public 方法上的@Transaction 注解。
若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。

具体实现步骤:

1)声明事务管理器

<!--声明事务管理器-->
<bean id="transactionManager">
	<class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="datasource" ref="datasource"/>
</bean>

2)开启注解驱动

<!--声明事务注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>

transaction-manager:事务管理器 bean 的 id

3)业务层 public 方法加入事务属性

@Transactionl(propagation = Propagation.REQUIRED,rollbackFor={NotEnoughException.class,NullPointerException.class})
public void buy(Integer goodsId,Integer amount){
    	Sale sale = new Sale();
 		sale.setGid(goodsId);
        sale.setNums(amount);
        Goods goods = goodsDao.selectGoods(goodsId);
        if(goods == null){
            throw new NullPointerException("没有商品");
        }
        if (goods.getAmount()<amount){
            throw new NotEnoughException("库存不足");
        }
        goods = new Goods();
        goods.setAmount(amount);
        goods.setId(goodsId);
        goodsDao.updateGoods(goods);
}
4、使用AspectJ的AOP配置管理事务

1)加入 aspectj 的依赖坐标

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

2)在容器中添加事务管理器

<!--声明事务管理器-->
<bean id="transactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransationManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

3)配置事务通知

<!--事务通知-->
<tx:advice id="buyAdvice" transaction-manager="transactionManager">
            <!--tx:attributes:配置事务属性-->
            <tx:attributes>
                <!--tx:method:给具体的方法配置事务属性,method可以有多个,分别给不同的方法设置事务
                    name:方法名称:1)完整的方法名称,不带有包和类
                                    2)方法可以使用通配符,*表示任意字符
                    propagation:传播行为,枚举值
                    isolation:隔离级别
                    rollback-for:你指定的异常类名,全限定类名。发生异常一定回滚
                -->
                <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                rollback-for="java.lang.NullPointerException,com.hxc.excep.NotEnoughException"/>

                <tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"
                           rollback-for="java.lang.Exception"/>

                <tx:method name="*" propagation="SUPPORTS"/>
            </tx:attributes>
        </tx:advice>

4)配置增强器

    <!--aop配置:通知应用的切入点-->
        <aop:config>
            <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
            <aop:advisor advice-ref="buyAdvice" pointcut-ref="servicePt"/>
        </aop:config>

十、使用 Spring 的器 监听器 ContextLoaderListener

 对于 Web 应用来说,ServletContext 对象是唯一的,一个 Web 应用,只有一个

ServletContext 对象,该对象是在 Web 应用装载时初始化的。若将 Spring 容器的创建时机,
放在 ServletContext 初始化时,就可以保证 Spring 容器的创建只会执行一次,也就保证了
Spring 容器在整个应用中的唯一性。

​ 当 Spring 容器创建好后,在整个应用的生命周期过程中,Spring 容器应该是随时可以被

访问的。即,Spring 容器应具有全局性。而放入 ServletContext 对象的属性,就具有应用的
全局性。所以,将创建好的 Spring 容器,以属性的形式放入到 ServletContext 的空间中,就
保证了 Spring 容器的全局性。

具体实现步骤:

1)注册监听器 ContextLoaderListener

<listener>
    <listener-class>
    	org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

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

2)指定Spring配置文件的位置

ContextLoaderListener 在对 Spring 容器进行创建时,需要加载 Spring 配置文件。其默认
的 Spring 配置文件位置与名称为:WEB-INF/applicationContext.xml。但,一般会将该配置文
件放置于项目的 classpath 下,即 src 下,所以需要在 web.xml 中对 Spring 配置文件的位置及
名称进行指定。

<context-param>
	<param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

3)获取spring容器对象

  • 直接从ServletContext中获取

从对监听器 ContextLoaderListener 的源码分析可知,容器对象在 ServletContext 的中存
放的 key 为 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。所以,可
以直接通过 ServletContext 的 getAttribute()方法,按照指定的 key 将容器对象获取到。

//获取容器
String attr = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
WebApplicationContext ac = (WebApplicationContext) this.getServletContext.getAttribute(arr);
  • 通过WebApplicationContextUtils获取

工具类 WebApplicationContextUtils 有一个方法专门用于从 ServletContext 中获取 Spring
容器对象:getRequiredWebApplicationContext(ServletContext sc)

WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext())
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值