Spring常用注解及用法总结

Spring中通过注解配置(使用的范围比较广)
1:首先我们需要在Spring容器中注册组件扫描器,Spring会从ClassPath下自动扫描,侦测,实例化具有特定注解的
组件,这些组件包括
    *@Component 基本注解,标识了一个受Spring容器管理的组件
    *@Respository标识的是持久层组件
    *@Service 标识的是业务层(服务层)组件
    *@Controller 标识的是表述层组件
  对于扫描到的组件,Spring有其自己的默认的命名策略,即使用的是用户定义的类名(只不过是把类的是一个字母小写)
  如果用户想自己想使用自定义的名称,可以在注解中通过value属性进行修改(如果只有value属性,可以省略)
2:仅有注解是不能够使用的,我们需要在Spring容器中注册组件扫描器,即<context:component-scan>
  base-package属性是用来指定需要扫描的基类包,Spring容器会扫描这个基类包及其子类包中所有的类
  如果我们需要扫描多个包时,包名之间用逗号隔开即可.
  resource-patten属性用来扫描指定的类,而不是所有的类.
  <context:include-filter>表示的是要包含的目标类
  <context:exclude-filter>表示的是要排除的目标类
  组件扫描器中可以包含多个这样的子节点.
  我们的spring是有默认的filter的,所以如果我们想要达到子节点的效果,需要关闭默认的filter
  即,
  <context:component-scan base-package="com.atguigu.spring.beans"
            use-default-filters="false">
  </context:component-scan>

3:如何使用注解简历Bean之间的关系
    在<context:component-scan>扫描组件的同时,还会自动注册AutowiredAnnotationBeanPostProcessor
        的Bean后置处理器,该处理器会自动装载@Autowired,@Resource,@Inject注解的属性.
        也就是说,我们可以通过以上三种注解,建立Bean之间的关系
    注意:@Autowired会自动装配具有兼容类型的单个的Bean属性,可以放在构造器,方法,方法的参数之前
        默认情况下,被@Autowired修饰的属性都需要被设置,若某一个实行不需要被设置时,可以把@Autowired
        的required的属性设置为false.
    默认情况下:当Spring容器中含有多个相同类型的Bean(比如一个接口有多个实现类的时候),通过类型
        的自动装配会报出不唯一Bean异常,我们可以通过在@Qualifier注解中提供bean名称
        该注解也能应用在方法的参数中.通过类名称指定装配哪一个Bean
    @Autowired也可以使用在List,集合,map中,其中会把Bean的名称当做键,bean本身当做值装配到map中.
4:Spring新特性:泛型依赖注入:
    可以为子类注入子类对应的泛型类型的成员变量的引用.父类中建立了引用关系,那么子类中也会建立
    对应的泛型关系,并且会把子类相应的泛型类型的成员变量注入.

Spring-aop面向切面编程
    1:我们使用面向切面编程的步骤如下:
        1> 使用@Component把表示切面的类放入到Spring容器中
        2> 使用@Aspect把类声明成切面
        3> 使用@Before("execution(目标方法的签名)")声明切面中到底是哪种通知,以及其对应的目标方法
        4> 在Spring 容器中使用<aop:axpectj-autoProxy></aop:aspectj-autoProxy>,他的作用,就是
            当容器找到了目标类要增强目标类时,自动的为目标类创建代理对象.
     2:如果我们想要了解织入的细节,我们可以在通知中添加参数JoinPoint,通过JoinPoint我们可以
        的到目标方法的方法签名,和目标方法的参数
        String name = JoinPoint.getSignature().getName();//目标方法签名
        Lise<> args = Arrays.asList(JoinPoint.getArgs());//目标方法参数
     3:关于execution()中的表达式的总结:
        * com.abc.aynu.aopClass.*(..)
        第一个*表示的是任意修饰符(public,private,等),任意返回值
        第二个*表示的是该包下的所有方法
        (..)表示的是匹配任意数量的参数(目标方法的形参我们都是不写的)
        如果接口及目标类和切面是在同一个包下,我们还可以省略包,* aopClass.*(..)
     4:@After("execution()")后置通知,会在目标方法返回结果之后,抛出异常之前执行,
        所以再后置通知中,无法访问目标方法的返回值.
     5:@AfterReturning(value="execution()",returning="")
        返回通知,可以访问到目标方法的返回值,通知中的形参和returning中的值保持一致,我们就可以在通知中
        访问到目标方法的返回值
     6:@AfterThrowing(value="execution()" throwing=""),异常通知,我们同样可以通知中捕获到异常信息
        我们可以指定具体的异常进行捕获,不是该异常,那么异常通知就不会被执行.
     7:@Around环绕着目标方法体执行.环绕通知必须要携带ProceedingJoinPoint类型的参数,该参数可以决定是否
        执行目标方法,并且环绕通知必须要有返回值,即目标方法的返回值.

        例如:@Around("execution()")
        public Object aroundMethod(ProceedingJoinPoint pjt){
            String name = pjt.getSignature().getName();//目标方法的签名.
            Object result = null;//目标方法的返回值
            ...                  //前置通知
            pjt.proceed();//执行目标方法
            ...                 //后置通知
            return result;
        }
     8:切面的优先级
        当有多个切面时,切面的优先级问题,我们可以是用@Order(数字),数字越小,优先级越高,
        指定切面的织入顺序.
     9:切入点表达式的复用
        当我们想重用切入点表达式的时候,我们可以这样,利用@PointCut("execution()"):
        @PointCut("execution()")
        public void declarePointCutExpression(){}
        然后我们就可以这样使用了,@Before("declarePointCutExpression()"),如果引用的表达式
        位于不同的包下,需要加上包名.

5:Spring的事务管理机制
        1:首先我们需要在Spring的容器中注册事务管理器
        2:然后在容器中注册事务注解驱动
        3:在我们需要的操作方法用@Transational,表示该方法的执行是支持事务的
            <!--注册事务管理器-->
            <bean id="transationManager" class="DataSourceTransationManager">
                <property name="datasource" ref="dataSource"/>
            </bean>

            <!--注册事务驱动-->
           <tx:annotation-drivern transation-managger="transationManager"/>

6:Spring中事务的传播行为
       当一个事务方法A.被另外一个事务B调用的时候,我们必须要指明事务A的应该怎么执行,是
       继续在现有事务中执行,还是开启新的事务,并在自己的事务中执行呢?
       事务的传播行为可以用事务的传播属性指定,Spring中提供了7种传播属性.
       常用的属性是required和requires_news
       Spring中默认的默认的事务属性是required,它默认的就是会在现有的事务中运行..
       required_news,也就是当方法在A事务中执行的过车高中遭遇了B事务,
       那么A事务会被挂起,然后会执行B事务,当B事务执行完毕的时候,继续执行A事务直至事务A结束.
       @Transational(propagation=REQUIRED或者是REQIURES_NEWS)指定事务的属性.

7:并发事务导致的问题
        当一个应用程序,或者不同的应用程序的多个事务在同一个数据集上并发执行时,可能会出现许多意外
      并发会导致一下三种问题:
        1> 脏读:对于两个事务,T1,T2.若T1读取了已经被T2更新了但还提交的字段,如果T2执行了回滚的操作
            那么T1读取的就是临时的无效的数据.
        2> 不可重复读:对于两个事务,T1,T2.T1读取了一个字段,T2更新了该字段,如果T1再次读取该字段,
            读取的值就会和之前的不同
        3> 幻读:对于两个事务,T1,T2.T1读取了一个表中的一个字段,然后T2在表中插入了几行记录,如果T1
            再次读取同一张表,就会多读出几行.
        解决方案:我们使用@Transational(isolation.READ_COMMMITED),我们使用isolation指定事务的
            隔离级别,最常用的就是READ_COMMITED,读已提交.Spring默认的情况下,会对所有的运行时异常
            进行回滚,通常情况下,我们去默认值就行.
        isolation的常用取值有四个:
            1> rollbackFor:通过类的类型指定执行回滚
            2> rollbackForClassName:通过类的全限定类名制动具体的类执行回滚
            3> norollbackFor:通过类的类型指定执行不回滚
            4> norollbackForClassName:通过类的全限定类名制动具体的类执行不回滚
        readOnly:取值为 true,false.设置为只读级别.
        timeout:取值为整数,单位是秒.它表示的是你这个事务方法在强制回滚之前最多可以占用多长时间
                它可以防止一个事务对连接占用的时间过长.超过该时间,会强制进行回滚.

猜你喜欢

转载自blog.csdn.net/dawiebazhanlang/article/details/83446475