DI 就是将类之间的关联交给 spring 容器进行,以前我们一个类要创建一个 connection 连接数据库,会进行 new 操作。有了spring IOC 容器之后,类 A 需要一个连接时,直接向容器说我要一个连接,IOC 容器会自动适当时候创建一个 connection 连接,然后将创建的对象使用各种方法注入到需要连接的类,完成调用
IOC(Inversion of Control):反转控制
由容器主动将需要的资源推送给需要的组件
IOC的实现:
BeanFactory
:IOC的基本实现,是spring 内部的基础设施,是面向Spring 本身,不是提供给开发人员使用的ApplicationContext
:BeanFactory 的子接口,提供了更多高级特性。面向Spring 的使用者,几乎所有的场合都使用 ApplicationContextClassPathXmlApplicationContext
:对应类路径下的 XML 格式的配置文件FileSystemXMLApplicationContext
:对应文件系统中的 XML 格式的配置文件
实现IOC 步骤
定义用来描述 bean 的配置的 java 类
解析 bean 配置,将 bean 的配置信息转换为上面的 BeanDefinition 对象保存在内存中,spring 中采用 HashMap 进行对象的存储,其中会用到一些 xml 解析技术
遍历存放 BeanDefinition 的 HashMap 对象,逐条取出 BeanDefinition 对象,获取 bean 的配置信息,利用 java的反射机制实例化对象,将实例化后的对象保存在另一个 Map 中3
BeanFactory与ApplicationContext
BeanFactory:比较原始,无法支持 spring 插件,例如AOP、Web应用。
ApplicationContext:是 FactoryBean 的子类,程序员使用中基本替代了 BeanFactory 工作
DI(Dependency Injection):依赖注入
就是在实例化 bean 时将相关联的类实例化并且注入
IOC 就是一种反转控制的思想,而 DI 是对 IOC 的一种具体实现
方式:
-
通过 bean 的
setXxx()
方法赋值<bean id="helloSpring" class="com.tuling.spring.HelloSpring"> <property name="hi" ref="hi"/> </bean>
-
通过 bean 的构造器
-
Spring 自动匹配合适构造器
<bean id="book" class="com.spring.bean.Book"> <constructor-arg value= "10010"/> <constructor-arg value= "Book01"/> </bean >
-
通过索引指定参数位置
<bean id="book" class="com.spring.bean.Book"> <constructor-arg value= "10010" index="0"/> <constructor-arg value= "Book01" index="1"/> </bean >
-
通过类型区分重载构造器
<bean id="book" class="com.spring.bean.Book"> <constructor-arg value= "10010" index="0" type="java.lang.Integer"/> <constructor-arg value= "Book01" index="1" type="java.lang.String"/> </bean >
-
-
p 命名空间
<bean id="person" class="com.tuling.life.Person" init-method="myInit" destroy-method="myDestroy" scope="singleton" p:name="张三" p:address="广州" p:phone="1590000000" />
-
静态工厂方法注入:调用静态方法创建 bean
//静态工厂 //class要写工厂的类;factory-method要写工厂类中用于创建bean的方法;constructor中写静态方法需要的参数 <bean id="cardStatic" class="com.util.StaticFactory" factory-method="getCar"> <constructor-arg value="1" /> </bean>
-
实例化静态工厂注入
<!-- 实例工厂 --> -首先创建一个工厂的bean <bean id="cardFactory" class="com.util.InstanceFactory"></bean> -factory-bean 指定前面已经创建的 bean; factory-method 指定工厂实例中用于创建 car 的方法; constructor-arg 指定创建 car 方法中传入的参数 <bean id="cardInstance" factory-bean="cardFactory" factory-method="getCar"> <constructor-arg value="2" /> </bean>
FactoryBean
已普通 bean 不同,其返回的对象不是指定类的一个实例,其返回的是该工厂 bean 的 getObject 方法所返回的对象。工厂 bean 必须实现 org.springframework.beans.factory.FactoryBean
接口。可以让我们自定义Bean的创建过程
作用:创建比较复杂的 bean
<bean id="product" class="com.spring.bean.ProductFactory">
<property name="productName" value="Mp3" />
</bean>
bean 作用域
dao层为什么不能用单例模式:因为单例模式下线程是共享资源的,dao层会创建和销毁连接(连接池会拿到或归还),多个线程会出现冲突
mybatis集成 spring 时,dao层(mapper)可以创建为单例,因为 spring 中使用了 threadLocal 进行安全处理
Spring生命周期
-
Spring IOC容器可以管理 bean 的生命周期,Spring 允许在 bean 生命周期内特定的时间点执行指定的任务。
-
Spring IOC容器对 bean 的生命周期进行管理的过程:
① 通过构造器或工厂方法创建bean实例
② 为bean的属性设置值和对其他bean的引用
③ 调用bean的初始化方法
④ bean可以使用了
⑤ 当容器关闭时,调用bean的销毁方法
-
在配置bean时,通过 init-method 和 destroy-method 属性为 bean 指定初始化和销毁方法
-
bean 的后置处理器
① bean 后置处理器允许在调用初始化方法前后对 bean 进行额外的处理
② bean 后置处理器对IOC容器里的所有 bean 实例逐一处理,而非单一实例。
其典型应用是:检查 bean 属性的正确性或根据特定的标准更改 bean 的属性。
③ bean后 置处理器需要实现接口:
org.springframework.beans.factory.config.BeanPostProcessor
。在初始化方法被调用前后,Spring 将把每个 bean 实例分别传递给上述接口的以下两个方法:
-
postProcessBeforeInitialization(Object, String)
-
postProcessAfterInitial ization(Object, String)
- 添加bean后置处理器后bean的生命周期
①通过构造器或工厂方法创建 bean 实例
②为 bean 的属性设置值和对其他 bean 的引用
③将bean实例传递给 bean 后置处理器的 postProcessBeforeInitialization()
方法
④调用 bean 的初始化方法
⑤将 bean 实例传递给 bean 后置处理器的 postProcessAfterInitialization()
方法
⑥bean可 以使用了
⑦当容器关闭时调用 bean 的销毁方法
自动装配
-
no:不自动装配,可读性高,不易出错
<bean id="people" class="com.pojo.Peopel"> <property name="name" value="张三"/> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> </bean>
-
byName:Spring 会根据 class 属性找到实体类,查询所有的 setter 方法,根据 setter 方法后面的名字在配置文件中找到 id 相同的 bean 进行注入
<bean id="people" class="com.pojo.Peopel" autowire="byName"> <property name="name" value="张三"/> </bean> <bean id="cat" class="com.pojo.Cat"/> <bean id="dog" class="com.pojo.Dog"/>
-
byType:Spring 自动寻找一个与该属性相同的 bean,进行注入(根据 class 进行注入)
<bean id="cat" class="com.pojo.Cat"/> <bean id="dog" class="com.pojo.Dog"/> <bean id="people" class="com.pojo.Peopel" autowire="byName"> <property name="name" value="张三"/> </bean>
-
constructor:使用构造方法的参数类型进行对象查找,相当于采用 byType 的方式。即 spring 会寻找与参数类型相同的 bean,通过构造函数注入(根据构造函数的参数进行按类型自动装配)
<bean id="cat" class="com.spring.auto.autowire.Cat"></bean> <bean id="dog" class="com.spring.auto.autowire.Dog"></bean> <bean id="people" class="com.spring.auto.autowire.Peopel" autowire="constructor"> <constructor-arg value="2" type="int"></constructor-arg> </bean>
-
default:默认采用上一级标签的自动装配的取值。
-
通过注解配置
- @component 普通组件
- @Repository 持久化组件
- @Service 业务逻辑层组件
- @Controller 表述层控制器
-
扫描组件
-
<context:component-scan base-package="com.spring.component"/>
-
base-packag 属性指定一个需要扫描的基类包,会扫描这个包及子包
-
多个包用
,
分隔 -
如果仅希望扫描包下所有类,可使用
resource-pattren
属性过滤<context:component-scan base-package="com.atguigu.component" resource-pattern="autowire/*.class"/>
-
AOP 面向切面编程
是对传统编程OOP(面向对面编程的补充)
AOP 编程操作对象主要是切面(aspect),而切面用于 模块化横切关注点(公共功能)
-
Aspect 切面:与业务无关,却被业务模块所共同调用的逻辑或者责任封装起来。降低耦合,有利于未来的可维护性。封装横切关注点信息的类,每个关注点体现为一个通知方法
-
核心关注点:业务处理的主要流程
-
横切关注点:与业务关系不大的部分。权限认证,日志,事务处理。
-
Advice 增强:切面必须完成的各个具体工作
-
Target 目标:被通知的对象
-
代理:向目标对象应用通知之后创建的代理对象
-
JointPoint 连接点:程序执行的某个特定位置。横切关注点在程序代码中的具体体现,对应程序执行的某个特定位置,如,某个方法调用前、后、方法捕捉异常后等
-
Pointcut 切点:通过正则或其他方式找到 Advice(增强)应作用于那个连接点 JointPoint
spring支持:默认使用 Java动态代理 来创建AOP 代理,这样就可以为任何接口实例创建代理(实现了接口的类也默认使用 java 动态代理)
当需要代理的类不是代理接口时,spring 会切换为使用CGLIB 代理(没实现接口)
<aop:aspectjautoproxy proxytargetclass=“true” /> 强制使用cglib
aspect 中的 order 属性定义优先级
JAVA动态代理与CGLIB
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokerHandler 来处理(InvokerHandler会通过反射接收被代理类的类对象,被代理方法,方法的参数)。JDK 动态代理只能对实现了接口的类生成代理,而不能针对类
CGLIB 动态代理是利用 asm 开源包,对代理对象的 class 文件加载进来,通过修改其字节码生成子类来处理。针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法、类或方法不要声明为final
事务
程序化事务管理:发生错误时,自己写事务回滚
声明式事务管理:使用注解
AspectJ
① @Before:前置通知,在方法执行之前执行
② @After:后置通知,在方法执行之后执行
③ @AfterRunning:返回通知,在方法返回结果之后执行
④ @AfterThrowing:异常通知,在方法抛出异常之后执行
⑥ @Around:环绕通知,围绕着方法执行
@Autowired与@Resource
- @Autowired:按照类型注入(byType)
@Autowired(required = false) 允许为空
@Autowired
@Qualifier("manageServiceImpl")
按照类型注入,当一个类型不是单例(有多个实例)则可以用 Qualifier 进行按 bean 名字选择(byName)
- @Resource:可以使用属性
name type
指定注入的类型(byName byType)- 不指定默认使用 byName
@Required:应用于 bean 属性的 setter 方法,如果尚未填充被注解的属性,容器抛出 BeanInitializationException(注意,spring中要开启注解)
@Autowired:可用在属性,方法,构造函数中。
方法上:创建类时,会自动注入参数,并执行该方法
构造方法:通过构造方法注入
Java变量的初始化顺序为:静态变量或静态语句块–>实例变量或初始化语句块–>构造方法–>@Autowired
属性上:byName注入
@Qualifier:当有多个同类型 bean 时,来根据 ID 选择其中一个
@RequestMapping:将 HTTP 请求映射到处理器中的方法上