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的配置(基于配置)

  1. 步骤

    • 添加Context和AOP名称空间
    • 开启注解扫描
    • 开启aop注解扫描
    • 将通知类和切点类都交给spring管理
    • 添加注解@Aspect表是是一个切面类
  2. 注解

注解 作用 实例
@Aspect 表示该类是一个切面类
@Pointcut 切入点表达式
@Before(“表达式名”)
@AfterReturning(“表达式名”)
@AfterThrowing(“表达式名”) 异常
@After(“表达式名”) 最终
@Around(“表达式名”) 环绕
  1. 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的声明式事务配置

  1. 步骤

    • 配置事务管理器,注入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 中基于注解的声明式事务配置

  1. 步骤

    • 配置事务管理器
    • 开启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>