本文最后更新于:2023年3月23日 上午
一、原理:
IOC(控制反转):(面向对象编程)
控制权由内部应用程序的代码转移到外部容器中去,控制权反转,由外部容器来控制程序之间的关系
DI(依赖注入):
内部应用程序依赖于外部容器给它创建并注入需要的外部资源,比如程序、组件之间的依赖关系等
AOP:(面向切面编程)
通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
利用AOP可以对业务逻辑的各个部分进行隔离,从而使其各个部分之间的耦合度降低,提高程序可重用性跟开发效率
二、Spring Bean作用域:
bean标签中有个属性叫“scope”,它就是作用域
1,singleton
单例嘛,自然是所有对Bean的请求只要id与bean的定义匹配,就会返回bean的同一个实例
2,prototype
每次对Bean请求的时候Spring IOC都会创建一个新的作用域(tip:对于有状态的Bean应该用prototype反之singleton)
3,request
针对每次http请求,Spring容器会根据相关的bean的定义创建一个全新的并且只在当前request内有效的实例
4,session
针对http session起作用,Spring会根据相关的bean的定义创建一个全新的并且只在当前session内有效的实例
误区:session不是关闭浏览器就结束生命周期,关闭浏览器只是jsessionid重建。服务器内存中的数据不会马上清理。
5,global session
类似http session作用域不过仅基于portlet的web应用中才有意义
三、Spring注入方式:
1,构造器注入
Spring采用反射的方式,通过构造方法完成注入:
1)引入Spring的支持
2)知道具体的类的构造方法跟参数,方便Spring创建对象
3)在代码中写入Spring配置文件:
1 2 3
| String configLocation="applicationContext.xml"; ApplicationContext context=new ClassPathXmlApplicationContext(configLocation); Something thing=context.getBean("thing",Something.class);
|
tip:在Spring中一切资源都是bean
2,setter注入(最主流做法)
setter注入利用Java Bean规范:
1)将构造方法设置为无参构造,然后利用setter注入为其设置的新值,也是通过java的反射技术实现
2)配置文件中设置:
1 2 3 4 5
| <bean id="role" class="com.etc.entity.Role"> <property name="id" value="20211212"></property> <property name="name" value="yy"></property> <property name="sex" value="girl"></property> </bean>
|
3,接口注入
有时资源并非来自自身系统而是来自于外界,此时数据库连接资源可以在Tomcat下配置,然后跳过JNDI的方式去获取
四、懒加载:
懒加载意思是容器启动的时候不创建对象,第一次要使用对象的时候才创建并且初始化
作用就是避免一旦bean非常多的时候Spring一启动就得一个个去实例化
懒加载只针对Spring创建bean为单例时才有意义,因为只有单例模式时才在Spring启动的时候创建bean,多例bean原本就是懒加载
配置方式:
1,xml配置,在bean中加个属性lazy-init="true"
,想要全局配置就在beans标签上加个default-lazy-init="true"
2,注解配置,在创建新对象的方法前加上@Lazy
五、自动装配:
先说手动装配是什么:
1 2 3 4 5 6 7
| <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="people" class="com.kuang.pojo.Peopel"> <property name="name" value="张三"/> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> </bean>
|
我们在peoplebean中手动装配了cat跟dog的bean,这就是手动装配
所以自动装配:
1,xml配置
在bean中加一个属性autowire="byName"
,
自动装配的方式有byName
、byType
、constructor
、default
、no
byName
:就是查询实体类中所有 setter方法的名字跟自己bean的id相同的自动装配
no
:默认,不自动装配
byType
:靠属性类型和bean的class进行识别。要保证 符合该type的bean唯一,否则会报错
constructor
:靠构造函数入参的属性名进行识别
2,注解
1)得先在xml里开启注解,加上标签<context:annotation-config/>
2)在类中声明变量的前面加上@Autowired
,比如
1 2
| @Autowired private Cat cat;
|
当然,你xml中的bean必须得有id为cat,class为Cat的标签~
tip:注解方式自动装配的时候会先按id找相同的,如果有多个相同的就会去下一个属性找相同比如class
ttip:使用@Autowired(required= false)
时,这等于告诉 Spring:在找不到匹配 Bean 时也不报错
六、面向切面:
advice(通知):新的公共功能。
joinpoint(连接点):通知能够插入代码的位置。代码会在连接点前、后或环绕(ProceedingJoinPoint)插入。
pointcut(切点): 通知插入代码的方法。代码会在切点指定的方法中插入。
aspect(切面):切点+通知(pointcut+advice)。
weaving:织入。
1,xml配置
1)创建一个接口,来个实现类
2)创建切面类,里面包含了beforeMethod
、after
、around
什么的方法
3)配置AOP
1 2 3 4 5 6 7
| <aop:config> <aop:pointcut expression="execution(* service.StudentService.*(..))" id="mypc"/> <aop:aspect ref="aspect" order="1"> <aop:before method="beforeMethod" pointcut-ref="pointcut"> …… </aop:aspect> </aop:config>
|
4)配置测试类
1 2 3
| ApplicationContext context=new ClassPathXmlApplicationContext(configLocation); Something thing=context.getBean("thing",Something.class); thing.add(10,5);
|
2,注解配置
1)通知类升级为切面类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component;
@Aspect @Component public class FreeAdvice {
@Pointcut("execution(* com.etc.PhoneService.*(..))") public void pointcut() { }
@Before("pointcut()") public void beforeLog(JoinPoint point) { System.out.println("准备执行移动业务"); }
@After("pointcut()") public void afterfee() { System.out.println("本次业务费用为10元"); } }
|
2)xml配置一下
1 2
| <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
|
3)然后跟上面一样来个测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package test;
import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired;
import com.etc.service.PhoneService; public class TestPhone { @Autowired private PhoneService phoneService; @Test public void test() { phoneService.call(); phoneService.send_sms(); }
}
|
3,动态代理,暂略
七、事务:
1,事务是一组操作,要么全部成功,要么全部失败。
spring支持事务的提交和回滚。有些框架,事务是必须的。框架中的应用:拦截器
2,事务特性 ACID
原子性
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性
指系统从一个正确的状态,迁移到另一个正确的状态.简单理解就是:事务前后数据的逻辑性必须是合理的。
隔离性
所有的数据库客户端都可以针对某张表同时执行事务。这些事务是隔离的。其实就是多线程并发。
持久性
一旦事务提交后,就无法回滚了。
3,事务分类
声明式事务(推荐,@Transactional
)
编程式事务 (TransactionManager
)
4,事务隔离级别(和mysql一致)
未提交读
提交读
可重复读
串行化
5,事务的传播行为
PROPAGATION_REQUIRED
(默认开启)
如果外部没有开启事务,则内部自己开启子事务
如果外部开启事务,则内部和外部属于同一个事务
PROPAGATION_REQUIRES_NEW
不论外部有没有开启事务,则内部自己都开启子事务
如果当前已存在事务,则直接挂起
PROPAGATION_NESTED
外部未开启事务,和require一样
外部开启事务,则内部方法变成子事务,可以一起回滚,内部的子事务可以独立回滚
PROPAGATION_MANDATORY
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
6,代码实现
1 2 3 4 5 6 7 8 9 10 11 12
| <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:advice id="myadvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="change*" propagation="REQUIRED"/> <tx:method name="find*" read-only="true"/> <tx:method name="userLogin" read-only="true"/> </tx:attributes> </tx:advice>
|
八、注解:
添加xsd->添加<context:annotation-config/>
->添加<context:component-scan base-package="*"/>
->简单整合hibernate并使用hibernateTemplate做增删改查工具
->介绍@Component
、@Resourece
、@Autowired
实现IOC功能
-><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
开启AOP的注解模式
九、与设计模式的联系:
Spring 中的单例模式:
创建bean为单例时
Spring 中的代理模式:
Spring 中的AOP 是代理模式的应用,有静态代理跟动态代理
Spring 中的工厂模式:
Spring中在各种BeanFactory以及ApplicationContext创建中都用到了典型的工厂方法模式
十、配置文件(标签):
tx通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| <?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:p="http://www.springframework.org/schema/p" 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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd "> <context:annotation-config/>
<context:component-scan base-package="*"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8&allowMultiQueries=true"></property> <property name="username" value="root"></property> <property name="password" value="2936283"></property> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> <property name="typeAliasesPackage" value="entity"></property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="dao"></property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:advice id="myadvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="change*" propagation="REQUIRED"/> <tx:method name="find*" read-only="true"/> <tx:method name="userLogin" read-only="true"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* service.*.*(..))" id="mypc"/> <aop:advisor advice-ref="myadvice" pointcut-ref="mypc"/> </aop:config> </beans>
|
aop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <context:annotation-config/>
<context:component-scan base-package="*"/> <aop:config> <aop:pointcut expression="execution(* service.UserService.userLogin(..))" id="mypc"/> <aop:pointcut expression="execution(* service.UserService.userRegister(..))" id="mypc1"/> <aop:pointcut expression="execution(* service.UserService.user*(..))" id="mypc2"/> <aop:pointcut expression="execution(* service.UserService.*(..))" id="mypc3"/> <aop:pointcut expression="execution(* service.*.*(..))" id="mypc4"/> <aop:aspect ref="madvice"> <aop:before method="beforelog" pointcut-ref="mypc"/>
<aop:after method="afterlog" pointcut-ref="mypc"/> </aop:aspect> <aop:aspect ref="padvice"> </aop:aspect> </aop:config> </beans>
|