spring知识点罗列
spring5
—张文军
文章目录
1. Ioc (控制反转,Inverse Of Control)
ico容器叫做控制反转或者是反转控制,将创建和管理类的权利交给spring容器,即ioc只是一个创建和管理类的容器。
控制反转:所谓控制反转,就是把创建对象(Bean)和维护对象(Bean)关系的权力从程序中转移到Spring容器中,而程序本身不再负责维护。
容器:其中最底层的代表着是Beanfactory。而ApplicationContext是在Beanfactory的基础上的。
当ClassPathXmlApplicationContext(“spring-config.xml”)执行的时候,Spring容器对象被创建,同时spring-config中配置的Bean就会被创建(依赖于反射机制)UserService userService =(UserService)applicationContext.getBean(“userService”);获取Spring容器中的对象。
2 .DI
DI(Dependency Injection),依赖注入。所谓依赖注入,实际上,DI和IOC是同一个概念,Spring设计者认为DI能更准确地表示Spring的核心技术。
依赖注入常用set方法注入,而其他比如构造方法注入比较少用。依赖注入可以注入简单数据类型,也可以注入复杂类型,复杂类型需要现在spring配置文件中配置过后,用ref进行注入。
3. 常用IOC注解开发
1. 配置如图
2. 注解分类:
相当于创建对象的 | 用于注入数据的 | 用于改变作用范围的(scope) | 用于改变生命周期的(init函数和destroy函数的) |
---|---|---|---|
@Compoent | @Autowired | @Scope | @PreDestroy |
@Service | @Resource | @PostConstruct | |
@Controller | @Qualifier | ||
@Repostory | @Value("${数据}") |
想要用注解,必须添加注解包和开启注解扫描 <context:component-scan base-package=“com.njau.account”/>
注意:@Autowired只能按照数据类型自动注入,@Qualifier不能单独使用,@Reseource可以任意注入(不同与前两个,这个属性用 name=“id”)。–》》》但是,这是那种数据注入都只能注入复杂数据类型,对简单数据类型无法注入 ,对简单数据只能用@value("${数据}")的方式注入!
3. 配置类(spring新注解)
注解名称 | 注解作用/注解注意事项 | 例子 |
---|---|---|
@Configuratiuon | 这是一个配置内(当注解是spring主配置的时候可以省略) | |
@ComponentScan | 组件扫描(开启注解,扫描注解的包) | |
@Bean | 将方法返回值作为Bea放入到容器中,name相当于id,如果没有,默认是方法名 | |
@Scop | 控制作用范围,多例还是单例(默认是单例,数据库或取得连接要用多例) | |
@Import | 向主配置类中导入其他配置,相当于@ComponentScan(basePackages = {“com.njau”,“config”}) | |
@PropertySource | 指定properties文件的位置并将数据放入到容器中,取得时候要用@value的方式取(要加classpath指在类路径下)(一般在主配置文件中加这个注解说明properties文件位置) |
注意:如果是自己写的类,直接用全部注解开发简单,如果是jar包或者是别人的类,则xml比较省事
4. 整合Junit
注解名称 | 注解作用/注解注意事项 | 例子 |
---|---|---|
@RunWith | 替换Junit中的main方法,让其能有ioc容器 | @RunWith(SpringJUnit4ClassRunner.class) |
@ContextConfiguration | 告知Junit配置位置和方式(@ContextConfiguration(classes =。。。。是注解类配置)(@ContextConfiguration(locations =…是xml配置) | @ContextConfiguration(classes = SpringConfiguration.class) |
注意:在使用spring5 的时候,Junit的版本必须是4.12以上版本!
4. AOP(面向切面编程 aspect oriented programming)
简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态***的技术,在不修改源码的基础上,对我们的已有方法进行增强 。
在spring中主要用动态***的方法将代码中大量重复的代码抽取出来聚合在一起(类),即横向抽取
1. spring中AOP的配置(基于xml)
步骤 | 例子 |
---|---|
1.导入aop名称空间 | |
2.将要被通知的类(增强的类)配置静ioc中 | |
3.将通知类交给spring管理 | |
一下是配置AOP | |
4. aop:config标明开始配置AOP | |
5.<aop:aspect配置切面(id :为切面指定一个唯一标示,ref : 指定通知bean的id) | |
6. <aop:befor 配置通知顺序和位置(method 通知需要执行的方法, pointcut 切入点表达式,标明对那个方法增强) | |
7.pointcut切入点表达式的写法:pointcut(“execution(表达式)”) | |
8. 表达式: | |
a. 访问修饰符 返回值 包名.包名.包名.类名.方法名 (也就是写类方法的方式,只是加上了具体的包名和类名) 如:pointcut="execution(public void com.njau.account.service.impl.AccourceServiceImpl.saveMoney()) | |
b.访问修饰符可以省略,其他报名和类名均可用通配符代替,包名及其子包名可以用 *… 的方式来实现通配,如: | |
c.访问修饰符可以省略,全通配写法: | |
d. 开发中一般写法是写到业务层实现类的所有方法: | |
9.切入点一般配置在切面之前 | |
10.环绕通知: | |
完整配置 1 如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="com.njau.account.service.impl.AccourceServiceImpl" id="accourceService">
</bean>
<bean class="com.njau.account.utils.Logger" id="logger">
</bean>
<!--开始配置AOP-->
<aop:config>
<!--指定切面,即那个通知-->
<aop:aspect id="logger" ref="logger">
<aop:pointcut id="as" expression="execution(* com.njau.account.service.impl.*.*(..))"></aop:pointcut>
<!--将上述切面与切入点进行关联,即指定那个方法是增强的类,那个方法是被怎强的类-->
<!--<aop:before method="printLog" pointcut="execution(public void com.njau.account.service.impl.AccourceServiceImpl.saveMoney())"></aop:before>-->
<!--访问修饰符可以省略 -->
<!--<aop:before method="printLog" pointcut="execution(* *..*.*(..))"></aop:before>-->
<!--前置通知-->
<aop:before method="before" pointcut-ref="as"></aop:before>
<!--後置通知-->
<aop:after-returning method="after" pointcut-ref="as"></aop:after-returning>
<!--異常通知-->
<aop:after-throwing method="exception" pointcut-ref="as"></aop:after-throwing>
<!--最終通知-->
<aop:after method="finall" pointcut-ref="as"></aop:after>
</aop:aspect>
</aop:config>
</beans>
完整配置 2 如下:(环绕通知)
/** * 环绕通知 * * @param joinPoint 在spring中通过ProceedingJoinPoint接口的proceed()得到切入点方法 * @return */
public Object around(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
Object proceed = null;
try {
System.out.println("环绕通知-------前置通知---------end");
/** * 切点方法执行(proceed(args)相当于当前切点的方法) */
proceed = joinPoint.proceed(args);
System.out.println("环绕通知-------后置通知---------1end");
return proceed;
} catch (Throwable e) {
System.out.println("环绕通知-------异常通知---------end");
throw new RuntimeException(e);
} finally {
System.out.println("环绕通知-------最终通知---------end");
}
}
2.spring中AOP的配置(基于配置)
-
步骤
- 添加Context和AOP名称空间
- 开启注解扫描
- 开启aop注解扫描
- 将通知类和切点类都交给spring管理
- 添加注解@Aspect表是是一个切面类
-
注解
注解 | 作用 | 实例 |
---|---|---|
@Aspect | 表示该类是一个切面类 | |
@Pointcut | 切入点表达式 | |
@Before(“表达式名”) | 前 | |
@AfterReturning(“表达式名”) | 后 | |
@AfterThrowing(“表达式名”) | 异常 | |
@After(“表达式名”) | 最终 | |
@Around(“表达式名”) | 环绕 |
-
spring配置(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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--开启注解扫描--> <context:component-scan base-package="com.njau"/> <!--开启AOP注解扫描--> <aop:aspectj-autoproxy/> </beans>
4.配置好的切面类
package com.njau.account.utils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /** * @author 张文军 * @Description:模拟日志记录(切面类) * @Company:南京农业大学工学院 * @version:1.0 * @date 2019/7/1621:12 */ @Component("logger") @Aspect public class Logger { /** * 切入点表达式 */ @Pointcut("execution(* com.njau.account.service.impl.*.*(..))") public void as() { } @Before("as()") public void before() { System.out.println("before记录日志!----11111"); } @AfterReturning("as()") public void after() { System.out.println("after记录日志!----22222"); } @AfterThrowing("as()") public void exception() { System.out.println("exception记录日志!----33333"); } @After("as()") public void finall() { System.out.println("finall记录日志!44444"); } /** * 环绕通知 * * @param joinPoint 在spring中通过ProceedingJoinPoint接口的proceed()得到切入点方法 * @return */ @Around("as()") public Object around(ProceedingJoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); Object proceed = null; try { System.out.println("环绕通知-------前置通知---------end"); /** * 切点方法执行(proceed(args)相当于当前切点的方法) */ proceed = joinPoint.proceed(args); System.out.println("环绕通知-------后置通知---------1end"); return proceed; } catch (Throwable e) { System.out.println("环绕通知-------异常通知---------end"); throw new RuntimeException(e); } finally { System.out.println("环绕通知-------最终通知---------end"); } } }
注意:我发现最好用自己写的环绕通知,其他如果用spring提供的通知在执行顺序上有点诧异
5. JDBCTelplate
1. 步骤
-
得到数据源datasource(DriverManagerDataSource)
-
将数据源注入到jabcTemplate中
<?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"> <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> </beans>
2. 使用
方法语句 | 使用范围 | 例子 |
---|---|---|
update(“sql”,…args) | 没有返回值得都用此方法(即,增删改),差别只是在sql语句和参数上 | jdbcTemplate.update(“update account set name=?,money=? where id=?”, “文军”, 9001,15); |
***下面是查询***用query方法 | ||
查询类型 | 方法 | 实例 |
查询所有 | query(String sql, RowMapper rowMapper, @Nullable Object… args);rowMapper是对查询单行结果的封装对象,spring有写好的类可以使用BeanPropertyRowMapper(T.class) | //查询所有金额大于900的账户 List accountList = jdbcTemplate.query(“select * from account where money > ?”, new BeanPropertyRowMapper(Account.class), 900f); |
查询返回一行或一类(聚合但不用group by) | queryForObject(String sql, Class requiredType, @Nullable Object… args) | Long aLong = jdbcTemplate.queryForObject("select count() from account where money > ?", Long.class, 900f); |
6.spring中的事务控制器
1. 概述
*spring 框架为我们提供了一组事务控制的接口(PlatformTransactionManager ) ,这组接口是在spring-tx-5.0.2.RELEASE.jar 中。spring 的事务控制都是基于 AOP 的,它既可以使用编程的方式实现,也可以使用配置的方式实现 。*
2. spring 中基于XML的声明式事务配置
-
步骤
- 配置事务管理器,注入datasource
- 配置事务通知(导入事物约束tx和aop)
- 配置AOP中的切入点表达式
- 配置切入点表达式和事务通知之间的关系
- 配置事务的属性(在事务通知里面配置)
配置如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="com.itheima.service.impl.IAccountServiceImpl" id="accountService">
<property name="IAccountDao" ref="accountDao"/>
</bean>
<!-- 配置账户的持久层-->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
<!--<property name="jdbcTemplate" ref="jdbcTemplate"></property>-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--配置事务管理器 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务源-->
<tx:advice transaction-manager="transactionManager" id="txAdvice">
<!--配置事务的属性-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!--配置AOP-->
<aop:config>
<!--配置AOP中的切入点表达式-->
<aop:pointcut id="pointcut" expression="execution(* com.itheima.service.impl.*.*(..))"/>
<!--配置切入点表达式和事务通知之间的关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
</beans>
3. spring 中基于注解的声明式事务配置
-
步骤
- 配置事务管理器
- 开启spring对注解事物的支持
- 在需要业务支持的地方加上@Transactional注解
配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.itheima"/>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--开启spring对注解事物的支持-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--配置事务管理器 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>