Spring简介
Spring是分层的JavaSE/EE应用full-stack轻量级开源框架
DI(依赖注入Dependency injection) :在容器创建对象后,处理对象的依赖关系。当前类需要用到的其他类对象的时候,由spring为我们提供,我们只需要在配置文件中说明依赖之间的关系
IOC底层是通过工厂类+xml文件的方式去实现解耦并将所有的对象在web容器启动时创建。
xml形式的spring框架搭建
1、配置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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
2、加载配置文件mybatis.properties
<!--1.加载配置资源--> <context:property-placeholder location="classpath:mybatis.properties"/>
3、配置druid外部资源
1 <!--3.配置外部资源德鲁伊--> 2 <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> 3 <property name="driverClassName" value="${jdbc.driver}"/> 4 <property name="url" value="${jdbc.url}"/> 5 <property name="username" value="${jdbc.username}"/> 6 <property name="password" value="${jdbc.pwd}"/> 7 </bean>
4、配置mybatis
1 <!--4.1配置工厂类对象 2 主要分析mybatis核心文件中有那些部分需要配置 比如 起别名 插件 资源环境(可以直接引用德鲁伊的) 3 --> 4 <bean class="org.mybatis.spring.SqlSessionFactoryBean"> 5 <property name="dataSource" ref="dataSource"/> <!--环境资源--> 6 <property name="typeAliasesPackage" value="com.itheima.domain"/> <!--起别名--> 7 </bean> 8 <!--4.2配置映射配置文件扫描--> 9 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 10 <property name="basePackage" value="com.itheima.mapper"/> <!--映射路径--> 11 </bean>
5、配置依赖注入(包括IOC与DI)
1 <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> 2 <property name="accountMapper" ref="accountMapper"/> 3 </bean>
6、声明事务管理对象
1 <!-- 5.声明事务管理对象 2 主要使用的是正对下面三种的事务处理的类,现在使用的是mybatis 3 DataSourceTransactionManager jdbc/mybatis 4 HibernateTransactionManager Hibernate 5 JtaTransactionManager 分布式事务管理 6 --> 7 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 8 <!--注入数据源--> 9 <property name="dataSource" ref="dataSource"/> 10 </bean>
7、声明事务通知
1 <!--6.声明事务通知 导入的必须是 tx的 千万不要选错成che那种--> 2 <tx:advice id="txAdvice" transaction-manager="transactionManager"> 3 <tx:attributes> 4 <tx:method name="*"/> <!--REQUIRED:如果有事务,就用当前事务,如果没事务,则开启一个新的事务 都为默认设置 一般更新修改操作--> 5 <tx:method name="find*" propagation="SUPPORTS" read-only="true"/> 6 <!--一般对查询类的方法进行过滤 传播方式为support为,当有事务就加入事务,没有事务就没有,为只读操作 7 一般用于查询操作--> 8 </tx:attributes> 9 </tx:advice>
8、设置事务的切点
1 <!--7. 设置事务的切点--> 2 <aop:config > <!--这里的proxy-target-class设置为true,动态代理就是cglib模式下的动态代理--> 3 <aop:pointcut id="pt" expression="execution(* com.itheima.service.*.*(..))"/> 4 <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/> <!--事务的切点配置需要是advisor--> 5 </aop:config>
9、aop 设置 配置切面
1 <!-- 8.设置切面--> 2 <bean id="advice" class="com.itheima.aop.AopAdvice"/>
10、织入
1 <!-- 9.配置织入--> 2 <aop:config > 3 <aop:pointcut id="pi" expression="execution(* com.itheima.service.*.*(..))"/> <!--设置切点--> 4 <aop:aspect id="" ref="advice"> <!--ref的属性值为通知--> 5 <aop:around method="around" pointcut-ref="pi"/> 6 </aop:aspect> 7 </aop:config>
纯注解的形式spring框架搭建
1、配置spring核心配置类
1 @ContextConfiguration//定义为核心类 2 @ComponentScan("com.itheima")//设置注解包扫描路径支持 3 @Import({MyBatisC.class, DruidC.class, TransactionC.class})//导入第三方进ioc容器 4 @EnableTransactionManagement(proxyTargetClass = true)//开启事务注解支持 5 @EnableAspectJAutoProxy(proxyTargetClass = true)//开启aop注解支持 6 public class SpringConfig { 7 }
//SpringConfig为核心配置类
2、配置第三方类
1 //德鲁伊的外部类 2 @PropertySource("classpath:mybatis.properties")//加载外部配置文件 3 public class DruidC { 4 5 @Value("${jdbc.driver}") 6 private String driver; 7 @Value("${jdbc.url}") 8 private String url; 9 @Value("${jdbc.username}") 10 private String username; 11 @Value("${jdbc.pwd}") 12 private String pwd; 13 14 //配置druid 15 @Bean("dataSource") 16 public DataSource getDataSource(){ 17 //创建java对象 18 DruidDataSource ds = new DruidDataSource(); 19 ds.setDriverClassName(driver); 20 ds.setUrl(url); 21 ds.setUsername(username); 22 ds.setPassword(pwd); 23 24 return ds; 25 } 26 } 27 28 //mybatis的外部类 29 public class MyBatisC { 30 @Bean //可以不加id spring已经搞好了,与xml一致 方法的参数中的值是默认有Autowired 所以不写是可以查询到结果的 31 public SqlSessionFactoryBean getSqlSessionFactoryBean(@Qualifier("dataSource") DataSource dataSource){ 32 SqlSessionFactoryBean sb = new SqlSessionFactoryBean();//创建对象 33 sb.setDataSource(dataSource);//获取资源 34 sb.setTypeAliasesPackage("com.itheima.domain");//设置别名 可以使用配置文件读取 35 return sb; 36 } 37 @Bean//创建获取MapperScannerConfigurer对象 可以不加id 38 public MapperScannerConfigurer getMapperScannerConfigurer(){ 39 MapperScannerConfigurer msc = new MapperScannerConfigurer(); 40 msc.setBasePackage("com.itheima.mapper");//指定创建的映射文件路径,将其注入ioc 41 return msc; 42 } 43 } 44 45 //事务的外部类 46 public class TransactionC { 47 48 @Bean 49 public PlatformTransactionManager getPlatformTransactionManager(@Autowired DataSource dataSource) { 50 return new DataSourceTransactionManager(dataSource); 51 } 52 }
3、配置切面类
1 @Component//注入ioc 2 @Aspect//标记为切面类 3 public class AopAdvice { 4 5 @Around("pt()") 6 public Object around(ProceedingJoinPoint pjp){ 7 System.out.println("我是环绕的前置通知..."); 8 Object ret=null; 9 try { 10 ret = pjp.proceed(); 11 System.out.println("我是环绕的后置通知..."); 12 } catch (Throwable throwable) { 13 throwable.printStackTrace(); 14 System.out.println("我是环绕的异常通知.."); 15 }finally { 16 System.out.println("我是环绕的最终通知.."); 17 } 18 return null; 19 } 20 21 @Pointcut("execution(* com.itheima.service.*.*(..))")//设置切点 22 public void pt(){ 23 } 24 }
4、将实现类 注入ioc容器,开启tx事务,进行aop加强
1 @Service//注入ioc容器 2 @Transactional(propagation = Propagation.NEVER)//定义该类具有事务 3 public class AccountServiceImpl implements AccountService { 4 @Autowired//依赖注入 5 public AccountMapper accountMapper; 6 7 public void updateAccount(String oName, String iName, double money) { 8 9 accountMapper.outUpdate(oName,money); 10 accountMapper.inUpdate(iName,money); 11 } 12 }
5、
1 public class AccountController { 2 3 @Test 4 public void test(){ 5 //加载核心配置 6 ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class); 7 AccountService accountService = ac.getBean(AccountService.class); 8 accountService.updateAccount("jack","lucy",250); 9 } 10 }
IOC配置
- bean
作用:定义spring中的资源,此标签定义的资源将受到spring控制
格式:
1 <beans> 2 <bean /> 3 </beans>
举例:
1 <bean id="beanId" name="beanName1,beanName2" class="ClassName" scope="singleton"></bean>
属性解析:
id:bean的名称,通过id值获取bean class:bean的类型(类的全限定类名)
name:bean的名称,可以通过name值获取bean,用于多人配合时给bean起别名
scope:定义bean的作用范围
spring默认的值为singleton 表示该对象是个单例的对象
prototype 表是该对象是个多例的对象
request、session、application、 websocket :设定创建出的对象放置在web
容器对应的位置
spring容器中的bean定义冲突问题
同id的bean,后定一的覆盖先定义的
导入配置文件可以理解为浆倒入的配置文件赋值zhantie到对应位置
导入配置文件的顺序与位置不同可能会导致最终程序运行结果不同
归属 bean标签 作用使用set方法的形式为bean提供资源
格式: <property /> 一个bean可以有多个property标签
举例:
<property name="propertyName" value="propertyValue"( ref="beanId")/>
name:对应bean中的属性名,要求该属性必须提供可访问的set方法(严格规范为此名称是set方法对应名称)
value:设定非引用类型属性对应的值,不能与ref同时使用
ref:设定引用类型属性对应bean的id ,不能与value同时使用
- 构造器注入
归属 bean标签 作用:使用构造方法的形式为bean提供资源,兼容早期遗留系统的升级工作(部分类没有提供无参构造,只有有参构造)
格式: <constructor-arg />
举例:
基本属性
<constructor-arg name="argsName" value="argsValue />
value:设定非引用类型构造方法参数对应的值,不能与ref同时使用
其他属性:
<constructor-arg index="arg-index" type="arg-type" ref="beanId"/>
ref:设定引用类型构造方法参数对应bean的id ,不能与value同时使用
<bean id="beanId" class="....."></bean>
type :设定构造方法参数的类型,用于按类型匹配参数或进行类型校验
- 集合类型数据注入
归属:property标签 或 constructor-arg标签
作用:注入集合数据类型属性
格式:
1 <property> 2 <list></list> 3 </property>
举例:
1 //集合类型数据注入——list 2 <property name="al"> 3 <list> 4 <value>itheima</value> 5 <value>66666</value> 6 </list> 7 </property> 8 9 //集合类型数据注入——props 10 <property name="properties"> 11 <props> 12 <prop key="name">itheima666</prop> 13 <prop key="value">666666</prop> 14 </props> 15 </property> 16 17 //集合类型数据注入——map 18 <property name="hm"> 19 <map> 20 <entry key="name" value="itheima66666"/> 21 <entry key="value" value="6666666666"/> 22 </map> 23 </property>
xmlns:context="http://www.springframework.org/schema/context"
2、加载指定的properties文件
<context:property-placeholder location="classpath:filename.properties">
3、读取数据
使用${.....}获取数据
<import resource=“config.xml"/>
注解模式
- 注解扫描功能
启动注解扫描,加载类中配置的注解项
<context:component-scan base-package="packageName"/>
扫描过程是以文件夹递归迭代的形式进行的
扫描过程仅读取合法的java文件
扫描时仅读取spring可识别的注解
扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器
- bean
名称
@Component @Controller @Service @Repository
定义在类的上方
作用:设置该类为spring管理的bean
属性为value 定义bean的访问id 默认
注解bean的作用域scope定义在类上
@scope
默认属性value 值为singleton
@value bean的非应用数据类型属性注入
作用:设置对应属性的值或者方法进行传参
注意:仅支持非引用数据类型数据,赋值时对所有的方法的参数全部赋值
@Autowired、@Qualifier bean的引用类型属性注入
位置:方法定义上方,属性定义上方
作用:设置对应属性的对象或对方法进行引用类型传参
举例:
1 @Autowired(required = false) 2 @Qualifier("userDao") 3 private UserDao userDao;
说明:@Autowired默认按类型装配,指定@Qualifier后可以指定自动装配的bean的id
方法的参数上如果不写是默认自动装配的
- 加载第三方资源
名称 @Bean 位置:方法定义上
作用:设置该方法的返回值作为spring管理的bean
举例:
1 @Bean("dataSource") 2 public DruidDataSource createDataSource() { return ……; }
说明:
因为第三方bean无法在其源码上进行修改,使用@Bean解决第三方bean的引入问题
该注解用于替代XML配置中的静态工厂与实例工厂创建bean,不区分方法是否为静态或非静态
@Bean所在的类必须被spring扫描加载,否则该注解无法生效
加载properties文件
名称:@propertySource
位置:类的上方 作用:加载配置文件的属性值
举例:
1 @PropertySource(value = "classpath:filename.properties") 2 public class ClassName { 3 @Value("${propertiesAttributeName}") 4 private String attributeName; 5 }
注意:不支持*通配格式,一旦加载,所有spring控制的bean中均可使用对应属性值
- 纯除注解格式
名称:@Configuration、@ComponentScan
位置:定义在类上方,该类为核心加载类
作用:作用:设置当前类为spring核心配置加载类
举例:
1 @ContextConfiguration//定义为核心类 2 @ComponentScan("com.itheima")//设置注解包扫描路径支持 3 @Import({MyBatisC.class, DruidC.class, TransactionC.class})//导入第三方进ioc容器 4 @EnableTransactionManagement(proxyTargetClass = true)//开启事务注解支持 5 @EnableAspectJAutoProxy(proxyTargetClass = true)//开启aop注解支持 6 public class SpringConfig { 7 }
说明:
@ComponentScan 开启注解扫描包路径
@Import 导入第三方进入ioc容器 第三方必须这样,否则无效
@EnableTransactionManagement(proxyTargetClass = true)//开启事务注解支持
@EnableAspectJAutoProxy(proxyTargetClass = true) 开启aop注解支持
注意:proxyTargetClass 是动态代理模式 默认为jdk的proxy模式,true就为cglib模式
- 依赖加载
@DependsOn
作用:控制bean的加载顺序,使其在指定bean加载完毕后再加载
配置在方法上,使@DependsOn指定的bean优先于@Bean配置的bean进行加载
配置在类上,使@DependsOn指定的bean优先于当前类中所有@Bean配置的bean进行加载
配置在类上,使@DependsOn指定的bean优先于@Component等配置的bean进行加载
位置:配置类定义的位置(类上)
作用:控制配置类的加载顺序
位置:bean定义的位置(类上或方法上)
作用:控制bean的加载时机,使其延迟加载
AOP简介
目标:将软件开发由手工制作走向半自动化/全自动化阶段,实现“插拔式组件体系结构”搭建
AOP优势
业务代码编码更简洁
业务代码维护更高效
业务功能扩展更便捷
AOP开发过程
-
-
正常的制作程序
-
将非共性功能开发到对应的目标对象类中,并制作成切入点方法
-
将共性功能独立开发出来,制作成通知
-
在配置文件中,声明切入点
-
在配置文件中,声明切入点与通知间的关系(含通知类型),即切面
-
-
运行阶段(AOP完成)
-
Spring容器加载配置文件,监控所有配置的切入点方法的执行
-
当监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置将通知对应的功能织入,完成完整的代码逻辑并运行
-
AOP配置
- aop:config
作用:设置AOP 归属beans标签
- aop:aspect
作用:设置具体的AOP通知对应的切入点 归属:aop:config标签
- aop:pointcut
作用:设置切入点 归属:aop:config标签、aop:aspect标签
-
id :识别切入点的名称 ---->切入点描述的是某个方法
-
expression :切入点表达式 ---->切入点表达式是一个快速匹配方法描述的通配格式,类似于正则表达式
切入点表达式格式:关键字(访问修饰符 返回值 包名.类名.方法名(参数)异常名)
*:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
.. :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写
+:专用于匹配子类类型
1 <beans> 2 <aop:config> 3 <aop:pointcut id="pointcutId" expression="……"/> 可以定义在config中 4 <aop:aspect ref="beanId">……</aop:aspect> 5 <aop:aspect> 6 <aop:pointcut id="pointcutId" expression="* *.com.itheima.service.*.*(..)"/> 7 </aop:aspect> 8 </aop:config> 9 </beans>
- AOP的通知类型共5种
前置通知:原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行
aop:before 作用:设置前置通知
应用:数据校验
后置通知:原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知
aop:after-returning 作用设置后置通知
应用:现场清理
最终通知:原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
aop:after 作用:设置最终通知
应用:返回值相关数据处理
异常通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
aop:after-throwing 作用设置异常通知
应用:对原始方法中出现的异常信息进行处理
应用:十分强大,可以做任何事情
-
method :在通知类中设置当前通知类别对应的方法
-
pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
-
pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
注解AOP
@Aspect
作用:设置当前类为切面类
位置:方法定义上方 作用:使用当前方法名作为切入点引用名称
注意:被修饰的方法忽略其业务功能,格式设定为无参无返回值的方法,方法体内空实现(非抽象)
五大通知
@Before @After @AfterReturning @AfterThrowing @Around
事务管理
J2EE开发使用分层设计的思想进行,对于简单的业务层转调数据层的单一操作,事务开启在业务层或者数据层并无太大差别,当业务中包含多个数据层的调用时,需要在业务层开启事务,对数据层中多个操作进行组合并归属于同一个事务进行处理
PlatformTransactionManager //此接口定义了事务的基本操作
TransactionDefinition //此接口定义了事务的基本信息
TransactionStatus //此接口定义了事务在执行过程中某个时间点上的状态信息及对应的状态操作
-
DataSourceTransactionManager 适用于Spring JDBC或MyBatis
-
HibernateTransactionManager 适用于Hibernate3.0及以上版本
-
JpaTransactionManager 适用于JPA
-
JdoTransactionManager 适用于JDO
-
JtaTransactionManager 适用于JTA
归属:beans标签 作用:专用于声明事务通知
1 <beans> 2 <tx:advice id="txAdvice" transaction-manager="txManager"> 3 </tx:advice> 4 </beans>
id :用于配置aop时指定通知器的id
transaction-manager :指定事务管理器bean
归属:tx:advice标签 作用:定义通知属性
1 <tx:advice id="txAdvice" transaction-manager="txManager"> 2 <tx:attributes> 3 </tx:attributes> 4 </tx:advice>
归属:tx:attribute标签 作用:设置具体的事务属性
<tx:attributes> <tx:method name="*" read-only="false" /> <tx:method name="get*" read-only="true" /> </tx:attributes>
位置:方法定义上方,类定义上方,接口定义上方
作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性
归属:beans标签
作用:开启事务注解驱动,并指定对应的事务管理器
位置:Spring注解配置类上方
作用:开启注解驱动,等同XML格式中的注解驱动