Spring中通过注解配置(使用的范围比较广)
1:首先我们需要在Spring容器中注册组件扫描器,Spring会从ClassPath下自动扫描,侦测,实例化具有特定注解的
组件,这些组件包括
*@Component 基本注解,标识了一个受Spring容器管理的组件
*@Respository标识的是持久层组件
*@Service 标识的是业务层(服务层)组件
*@Controller 标识的是表述层组件
对于扫描到的组件,Spring有其自己的默认的命名策略,即使用的是用户定义的类名(只不过是把类的是一个字母小写)
如果用户想自己想使用自定义的名称,可以在注解中通过value属性进行修改(如果只有value属性,可以省略)
2:仅有注解是不能够使用的,我们需要在Spring容器中注册组件扫描器,即
base-package属性是用来指定需要扫描的基类包,Spring容器会扫描这个基类包及其子类包中所有的类
如果我们需要扫描多个包时,包名之间用逗号隔开即可.
resource-patten属性用来扫描指定的类,而不是所有的类.
组件扫描器中可以包含多个这样的子节点.
我们的spring是有默认的filter的,所以如果我们想要达到子节点的效果,需要关闭默认的filter
即,
3:如何使用注解简历Bean之间的关系
在
的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 容器中使用
当容器找到了目标类要增强目标类时,自动的为目标类创建代理对象.
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,表示该方法的执行是支持事务的
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:取值为整数,单位是秒.它表示的是你这个事务方法在强制回滚之前最多可以占用多长时间
它可以防止一个事务对连接占用的时间过长.超过该时间,会强制进行回滚.