目录
🗡Spring简介
Spring是一个分层的java框架
内核:IoC控制反转与AOP面向切面编程
IOC的概念
控制反转,把创建对象的权力交给框架(容器)。原理是反射与工厂模式
有依赖注入和依赖查找两种方式实现。
🗡Spring使用
☘使用maven管理项目
(1) 首先创建maven工程
(2)设置setting.xml配置文件以及maven仓库地址
(3)在pom.xml文件内添加spring依赖,maven会自动下载相应的jar包
☘创建一个spring配置文件(命名为bean.xml,可以任意命名,对应mybatis内整合时的applicationContext.xml)
使用bean标签配置对应的类(id与类的全路径)
☘当需要某一个类的对象时候,从核心容器内获取对象
ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
再调用ac.getBean("id")
得到对象,id则是在bean.xml中配置对应类的id
☘ApplicationContext三个常用实现类
ClassPathXmlApplicationContext
:加载类路径下的配置文件
FileSystemXmlApplicationContext
:加载磁盘任意路径下配置文件(需要访问权限,一般不选用)
AnnotationConfigApplicationContext
:读取注解创建容器,参数是被 @Configuration 注解过的类(类名.class)
☘核心容器的两个接口
ApplicationContext
:(单例对象适用)
该接口构建的核心容器,创建对象采用的策略是立即加载方式,一读取完配置文件,马上创建对象。
BeanFactory
:
该接口创建对象采用的策略是延迟加载方式,当根据id获取对象时再创建对象
🗡spring对bean的管理
☘创建bean的三种方式
▪使用默认的构造函数
<bean id="指定的ID" class="bean所属类的全类名">
▪使用普通工厂中的方法创建对象(使用某个类中的方法创建对象),并存入spring容器
<bean id="" factory-bean="工厂类对象在ioc容器内的id" factory-method="工厂方法名"/>
▪使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象),并存入spring容器
<bean id="" class="工厂全类名" factory-method="工厂静态方法名"/>
☘bean对象的作用范围
▪bean标签的scope属性
作用:指定bean作用范围
取值:singleton 单例(默认)
prototype 多例
request 作用于web应用请求范围
session:作用于web应用会话范围
global session 全局session,作用于多台服务器的共用session
☘bean对象的生命周期
▪单例对象:容器创建时对象出生,当容器存在对象存在,容器销毁时对象销毁
▪多例对象:当使用对象时spring创建对象,对象只是要使用就一直存在,当对象长时间不用且没有被引用,由java垃圾回收器回收
🗡spring依赖注入(DI)
☘spring对依赖关系的维护
☘能注入的3种数据:
▪基本类型和String
▪其他bean类型(配置文件中或注解配置过的bean)
▪复杂/集合类型
☘注入的方式: (下面进行具体描述)
▪使用构造器提供
▪使用set方法提供
▪使用注解提供
🕊构造器注入:(在创建bean对象时,必须注入数据)
▪在<bean>
标签内部使用标签<constructor-arg>
▪<constructor-arg>
标签内的属性:
name
给构造函数中指定名称的参数赋值
value
用于提供基本类型和string类型数据
ref
用于指定其他bean类型数据,指的是在spring的Ioc容器中出现过的bean对象
例1:将带有构造函数的类配置到spring容器中,并进行构造器注入
🕊set方法注入:(创建bean对象时可以使用默认构造函数,如果类中某个成员必须有值,set注入无法保证,相比于构造器注入,set注入更常用)
▪在<bean>
标签内部使用标签<property>
▪<property>
标签内的属性:
name
指定注入时所调用的set方法名称
value
,ref
属性同上
例2:将带有set方法的类配置到spring容器中,并进行set方法注入
🗡Spring注解
🗼Spring容器有两种配置方式,XML配置与其的替代方法:基于注解的配置。
🗼使用注解前需要导入AOP包并且在Spring的xml配置文件中添加context名称空间。
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
🗼常用的几种注解
⛩用于创建对象的注解(作用和在xml配置文件编写<bean>
标签实现的功能是一样的)
@Component
作用:把当前对象存入spring容器中
属性:value 用于指定bean的id,默认值时当前类名首字母小写 @Component(value = "指定的ID")
配置:在spring配置文件内使用 context:component-scan 标签告知spring在创建容器时要扫描的包
spring框架提供明确分层的注解,作用与属性与@Component相同 ,是其衍生注解:
@Controller
应用在MVC层(控制层)
@Service
业务逻辑层
@Repository
持久层
⛩用于注入数据的注解(作用和在<bean>
标签中的<property>
实现的功能是一样的)
@Autowired
作用:自动按照类型注入
✔只要容器中为唯一的一个bean对象和需要注入的变量类型匹配,就将该bean装配给@Autowired指定的变量
✔ 如果ioc容器内不止一个bean类型与要注入的变量类型匹配,则查看有无bean的ID与要注入的变量名称匹配,匹配则注入。
✖如果ioc容器中没有任何bean的类型与要注入的变量类型匹配则失败报错
出现位置:变量或方法上
@Qualifier
作用:在按照类注入基础上再按照名称注入,再给类成员注入时不能单独使用(必须和@Autowired组合使用),但是在给方法参数注入时可以。
👍最佳的标签:
@Resource
作用按照指定的id得到容器内的bean并注入到变量中
属性:name
指定容器内bean的id
以上三种注入都只能注入其他bean类型的数据,基本类型和String类型无法使用上述注解实现,集合类型的注入只能通过xml实现。
@Value
作用:用于注入基本类型和String类型数据
属性:value 指定数据的值,可以使用SpEL表达式
⛩用于改变作用范围的注解(作用和在<bean>
标签中使用scope属性实现的功能是一样的)
@Scope
作用:指定bean的作用范围
属性:value取值singleton(默认)或prototype
⛩和bean对象生命周期相关的注解(作用和在<bean>
标签中init-method与destroy-method实现的功能是一样的)
@PreDestroy
作用:指定销毁方法
@PostConstruct
作用:指定初始化方法
🗡Spring新注解
🏯@Configuration
作用:指定当前类是一个配置类
🏯@ComponentScan
作用:通过注解指定spring在创建容器时要扫描的包,使用该注解作用等同于xml配置中的 context:component-scan
属性:value
和basePackages
作用一样,指定创建容器时要扫描的包
🏯@Bean
作用:将当前方法的返回值作为bean对象存入spring的ioc容器中
属性:name
用于指定存入容器内bean的id,默认值是当前方法的名称
细节:当我们使用该注解配置的方法有参数,spring框架会去容器中查找有没有可用的bean对象,查找方式与@Autowired
注解相同,并且可用在参数前使用@Qualifier
注解
🏯@Import
作用:在一个配置类里面导入其他的配置类,带有@Import注解的是父配置类,导入的是子配置类
属性:value:指定其他配置类的字节码,@Import(配置类名.class)
🏯@PropertySource
作用:用于指定properties文件的位置
属性:value
:指定文件名称路径,classpath表示类路径下
🏯@ImportResource
作用:导入spring的xml配置文件,实现注解与配置文件共同创建ioc容器
属性:value
:指定配置文件路径,classpath表示类路径下
使用注解的方法将jar包中的bean对象放入容器的方法:(在Spring的xml内配置第三方jar包对象的替换方法)
新建一个配置类,使用@Configuration
注解,@ComponentScan
指定创建容器时扫描的包,新建一个创建jar包中的bean对象方法,返回该对象。并使用@Bean
注解将其返回的对象放入容器内(还可以使用@Scope
注解配置多例模式)。
得到容器的时候使用AnnotationConfigApplicationContext类,将@Configuration
注解的配置类当作参数传入进去即可。
ApplicationContext ac=new AnnotationConfigApplicationContext(“配置类名.class”);
测试代码:
🗡spring整合Junit
步骤:
(1)导入spring整合junit的jar(坐标 )
(2)使用junit提供的@RunWith
注解把原有的main方法替换成spring提供的
(3)告知spring运行器,ioc容器是基于xml还是注解创建的,并指定位置
locations
:指定xml文件的位置,加classpath关键字表示在类路径下
classes
:指定注解类所在位置
🗡动态代理
作用:不修改源码的基础上增强方法 (AOP的原理)
基于接口动态代理
使用Proxy类的newProxyInstance方法创建代理对象,被代理类最少需要实现一个接口
newProxyInstance()
方法参数:
ClassLoader
:用于加载代理对象字节码的,和被代理对象使用相同的类加载器
Class[]
:字节码数组,让代理对象和被代理对象有相同的方法(继承同一个接口)
InvocationHandler
接口:定义如何代理的类,可以使用匿名内部类,该类只有一个方法invoke(),执行被代理对象任何接口方法都会经过该方法。
基于子类的动态代理
使用第三方cglib库,使用Enhancer类的create方法创建代理对象
create方法参数:
Class
:指定被代理对象的字节码
Callback
:定义如何代理的接口,一般情况写该接口的子接口实现类MethodInertceptor
通过动态代理管理事务:
首先定义一个管理连接的工具类,将连接与ThreadLocal线程对象绑定。
然后定义一个事务管理类,内置一个连接管理类对象
将这两个bean都存放的ioc容器中(可以在xml配置或注解配置)
然后创建一个工厂类,定义一个生成service对象的代理对象的方法,使用这个代理对象的service可以进行事务管理。
🗡AOP 面向切面编程
🍣通过预编译的方式和动态代理实现程序功能统一维护
🍣在spring中通过配置的方式实现上面动态代理代码实现的功能
Joinpoint(连接点):
指被那些被拦截到的点,在spring中这些点指的是方法
Pointout(切入点):
指的是拦截的Joinpoint其中需要进行方法增强的方法
Advice(通知):
指的是拦截到Joinpoint要做的事情就是通知,类型有前置通知,后置通知,异常通知,最终通知,环绕通知
Target(目标对象):
代理的目标对象
Weaving(织入):
把增强应用到目标对象来创建新代理对象的过程
Proxy(代理):
一个类被AOP直入增强后,就产生一个结果代理类
Aspect(切面):
切入点和通知的结合
🍣实现AOP的步骤
开发阶段:编写业务核心代码,把公用代码抽取出来制作成通知,在配置文件内声明切入点和通知之间的关系
运行阶段:spring框架监控切入点方法执行,一旦监控到切入点方法运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象对应位置将通知功能织入。
🍣Spring基于XML配置AOP:
首先配置maven依赖:
编写业务层代码以及通知类代码
在配置文件内添加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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置springIOC,把service对象配置进容器-->
<bean id="accountService" class="cn.xjh.service.Impl.AccountServiceImpl"/>
<!--spring中基于XML的AOP配置步骤
1.把通知的Bean交给spring管理
2.使用aop:config标签开始aop配置
3.使用aop:aspect配置切面
id属性:给切面一个唯一标识
ref属性:指定通知类bean的Id
4.在aop:aspect标签内部使用对应标签配置通知类型
示例aop:before配置前置通知,method属性用于指定通知类Logger中哪一个方法是前置通知;pointcut属性配置切入点表达式,含义是对哪些方法进行增强
切入点表达式写法:
关键字:execution(表达式)
表达式写法:访问修饰符+返回值+包名+类名+方法名(参数列表)
全通配写法:* *..*.*(..) 省略访问修饰符,其他用通配符代替-->
<bean id="logger" class="cn.xjh.utils.Logger"/>
<!--配置AOP,默认是基于接口动态代理-->
<aop:config>
<!--配置切面-->
<aop:aspect id="logAdvice" ref="logger">
<!--配置通知类型,并建立通知方法和切入点方法关联-->
<aop:before method="printLog" pointcut="execution(public void cn.xjh.service.Impl.AccountServiceImpl.saveAccount())"/>
<!--还可以使用 aop:pointcut标签配置切入点表达式,就可以在通知标签内直接引用。-->
</aop:aspect>
</aop:config>
</beans>
🍣Spring基于注解配置AOP(环绕通知):
首先在spring配置文件内开启注解支持
将业务层bean放入容器中,在通知类里进行配置。
使用@Aspect
指定该类是通知类,@Pointcut
定义切入点表达式,给业务层的saveAccount()
方法配置通知,@Around
注解指定环绕通知。
环绕通知:包含了前置,后置,异常,最终通知
🗡Spring JdbcTemplate
🔨是spring框架提供的一个对象。对原始Jdbc API对象简单封装
🔨构造:JdbcTemplate jdbcTemplate=new JdbcTemplate(数据源);
Spring内置连接数据源对象:DriverManagerDataSource
🔨CRUD操作:
增删改:jdbcTemplate.update("sql语句",语句的参数);
查询:jdbcTemplate.query("sql语句",new BeanPropertyRowMapper<要封装的对象>(对象类的字节码),语句的参数);
查询一行一列(聚合函数):jdbcTemplate.queryForObject("sql语句",结果的类型,语句的参数);
🗡Spring声明式事务
Spring通过事务管理器(PlatformTransactionManager的子类)创建事务。与此同时会设置事务通知的隔离级别、传播行为、超时时间等属性。
🌍spring中基于xml的声明式事务控制配置步骤
1.配置事务管理器
2.配置事务的通知(此时需要导入事务的约束,tx名称空间和约束,同时需要aop的tx:advice配置事务通知,其属性id是事务通知唯一标识,transaction-manager给事务通知提供一个事务管理器引用)
3.配置AOP中的通用切入点表达式
4.建立事务通知和切入点表达式的对应关系
5.配置事务的属性(在事务的通知tx:advice标签内部 )
isolation
:指定事务隔离级别,默认值是DEFAULT使用数据库默认隔离级别
propagation
:指定事务传播行为,默认值是REQUIRED,表示一定有事务(增删改方法选择,查询方法可以选择SUPPORTS)
read-only
:用于指定事务是否只读,只有查询方法能设置true,默认值为false
timeout
:指定事务超时时间,默认值-1,表示不会超时
rollback-for
: 指定一个异常,当发生该异常事务回滚,产生其他异常事务不回滚
no-rollback-for
: 指定一个异常,当发生该异常事务不回滚,产生其他异常事务回滚
基于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: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">
<!--配置jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.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 name="url" value="jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="xjh1999"/>
</bean>
<bean id="accountDaoImpl" class="cn.xjh.dao.Impl.AccountDaoImpl">
<constructor-arg name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="accountService" class="cn.xjh.service.Impl.AccountServiceImpl">
<constructor-arg name="dao" ref="accountDaoImpl"/>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--*代表切入点的所有方法,select*表示切入点内以select开头的所有方法-->
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!--配置AOP-->
<aop:config>
<!--配置切入点表达式-->
<aop:pointcut id="pt1" expression="execution(* cn.xjh.service.Impl.*.*(..))"/>
<!--建立事务通知和切入点表达式的对应关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
</aop:config>
</beans>
🌍spring中基于注解的声明式事务控制配置步骤
1.配置事务管理器
2.开启spring对注解事务支持:tx:annotation-driven 标签
3.在需要事务支持的地方(类或者方法上)使用@Transactional
注解