IOC
bean.xml文件:把对象创建交给spring来管理
spring对bean的管理细节
1.创建bean的三种方式
2.bean对象的作用范围
3.bean对象的生命周期
创建bean的三种方式
-
第一种方式:采用默认构造函数创建
在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。 -
第二种方法:使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)
-
第三种方法:使用普通工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)
bean的作用范围调整
bean标签 的scope属性:
作用:用于指定bean的作用范围,
取值:
singleton:单例的(默认的)
prototype:多例的
request:作用于web应用的请求范围
session:作用于web应用的会话范围
global-session:作用于集群环境的会话范围(全局会话范围)
bean对象的生命周期:
单例类:
出生:当容器创建时对象出生
活着:容器销毁,对象消亡
死亡:容器销毁,对象消亡
总结:单例对象的生命周期和容器相同
多例类:
出生:当对象使用spring框架时为我们创建
活着:对象在使用过程中就一直活着
死亡:当对象长时间不用,且没有别的对象引用时,由java垃圾回收器回收
ApplicationContext常用的三个实现类:
ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话,加载不了。(更常用)
FileSystemXmlApplicationContext:它可以加载磁盘下任意路径下的配置文件(必须有访问权限)
AnnotationConfigApplicationContext:用于注解创建容器
核心容器的两个接口引发的问题:
ApplicationContext: 单例对象适用
他在构建核心容器时,创建对象采取的策略是立即加载的方式.也就是说,一读取完配置文件马上就创建文件中配置的对象
BeanFactory: 什么时候创建对象什么时候用,多例对象适用
他在构建核心容器时,创建对象采取的策略是延迟加载的方式.也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象
spring中的依赖注入
依赖注入: Dependency Injection
Ioc的作用:
降低程序间的耦合(依赖关系)
依赖关系的管理:
以后都交给spring来维护
在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明
依赖关系的维护:就称之为依赖注入。依赖注入:
能注入的数据:有三类
基本类型和string
其他bean类型(在配置文件中或者注解配置过的bean)
复杂类型/集合类型
注入的方式:有三种
第一种:使用构造函数提供
第二种:使用set方法提供干
第三种:使用注解提供
name
index
type
value
ref:在spring核心容器中出现过的对象
<bean id="accountService" class="my.stu.service.impl.AccountServiveImpl">
<!-- <constructor-arg name="name" value="cccyyj"></constructor-arg>-->
<constructor-arg name="name" value="连中文都快可以,spring太腻害了叭"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
<bean id="accountService2" class="my.stu.service.impl.AccountServiceImpl2">
<property name="myArr">
<array>
<value>aaa</value>
<value>23</value>
<value>444</value>
</array>
</property>
<property name="myList">
<list>
<value>sas</value>
<value>sas</value>
<value>sasjh</value>
</list>
</property>
<property name="mySet">
<set>
<value>sas</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="a" value="hsahsjk"></entry>
<entry key="2" value="df"></entry>
<entry key="3" value="aa"></entry>
<entry key="4" >
<value>42</value>
</entry>
</map>
</property>
<property name="properties">
<props>
<prop key="aa">sss</prop>
<prop key="11">333</prop>
<prop key="aa">6666</prop>
</props>
</property>
</bean>
过滤器(Filter)与拦截器(Interceptor)区别:
1、过滤器是基于函数回调,而拦截器是基于java的反射机制;
2、过滤器是servlet规范规定的,只能用于web程序中,而拦截器是在spring容器中,它不依赖servlet容器
3、过滤器可以拦截几乎所有的请求(包含对静态资源的请求),而拦截器只拦截action请求(不拦截静态资源请求)
4、过滤器不能访问action上下文及值栈里的对象,而拦截器都是可以的。
5、拦截器可以获取spring容器里的对象,而过滤器是不行的
6、拦截器在action的生命周期内是可以多次调用,而过滤器只在容器初始化时被调用一次。
原文链接:https://blog.csdn.net/qq_40350405/article/details/90073673
AOP:
spring中基于xML的AOP配置步骤
1、把通知Bean也交给spring来管理
2、使用aop:config标签表明开始AOP的配置
3、使用aop:aspect标签表明配置切面
id:给切面提供唯一识别的标识
ref:指定通知类bean的id
4、在aop:aspect标签的内部使用对应标签来配置通知的类型
我们现在示例是让printLog方法在切入点方法执行之前之前:所以是前置通知
aop:before:表示配置前置通知
method属性:用于指定Logger类中哪个方法是前置通知
pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强
切入点表达式的写法:
关键字:execution(表达式)
表达式:
访问修饰符 返回值 包名.包名.包名…类名.方法名(参数列表)
标准的表达式写法:public void my.stu.service.impl.AccountService.saveAccount()
返回值可以使用通配符,表示任意返回值:* my.stu.service.impl.AccountService.saveAccount()
包名可以使用通配符,表示任意包。但是有几级包,就要写几个*:* ....AccountService.saveAccount()
包名可以使用…表示当前包,及其子包:* …AccountService.saveAccount()
类名,方法名都可以用代替:* ….() ps:有参数的没有执行
参数列表:
可以直接写数据类型:
基本类型直接写名称 : int ps: ….(int) 只执行有参数的方法
引用类型写包名.类名的方式 : java.lang.String
可以使用通配符表示任意类型: ….() ps:还是只有update执行,有参数的执行
可以使用…表示有无参数,有无参数都可以运行:三个方法全部被增强
全通配写法:
* ….*(…)
实际开发中切入点表达式的通常写法:
切到业务层实现类下的所有方法
* my.stu.impl..(…)
<!--配置Logger类-->
<bean id="logger" class="my.stu.util.Logger"></bean>
<!-- 配置AOP-->
<aop:config>
<!-- 配置切面-->
<aop:aspect id="logAdvice" ref="logger">
<!-- 配置通知类型,并且建立通知方法和切入点方法的关联-->
<!-- <aop:before method="printLog" pointcut="execution( * *..*.*(..))"></aop:before>-->
<!-- <aop:before method="printLog" pointcut="execution(* my.stu.service.impl.AccountService.saveAccount())"></aop:before>-->
<!-- <aop:before method="printLog" pointcut="execution(* *.*.*.*.AccountService.saveAccount())"></aop:before>-->
<aop:before method="printLog" pointcut="execution(* *..*.*(..))"></aop:before>
</aop:aspect>
</aop:config>
<bean id="accountService" class="my.stu.service.impl.AccountService"></bean>
<!--配置Logger类-->
<bean id="logger" class="my.stu.util.Logger"></bean>
<!-- 配置AOP-->
<aop:config>
<!-- 配置切面-->
<aop:aspect id="logAdvice" ref="logger">
<!-- 配置前置通知:切入点方法之前执行-->
<!-- <aop:before method="beforePrintLog" pointcut="execution(* *..*.*(..))"></aop:before>-->
<!-- <!– 配置后置通知:切入点方法正常执行后执行,他和异常通知永远只能执行一个–>-->
<!-- <aop:after-returning method="afterReturningPrintLog" pointcut="execution(* *..*.*(..))"></aop:after-returning>-->
<!-- <!– 配置异常通知:切入点方法异常后执行,他和后置通知永远只能执行一个–>-->
<!-- <aop:after-throwing method="afterThrowingPrintLog" pointcut="execution(* *..*.*(..))"></aop:after-throwing>-->
<!-- <!– 配置最终通知:无论切入点方法是否正常都执行–>-->
<!-- <aop:after method="afterPrintLog" pointcut="execution(* *..*.*(..))"></aop:after>-->
<!--<!– 配置切入点表达式:id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容–>-->
<aop:before method="beforePrintLog" pointcut-ref="pt1" ></aop:before>
<!-- 配置后置通知:切入点方法正常执行后执行,他和异常通知永远只能执行一个-->
<aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1" ></aop:after-returning>
<!-- 配置异常通知:切入点方法异常后执行,他和后置通知永远只能执行一个-->
<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1" ></aop:after-throwing>
<!-- 配置最终通知:无论切入点方法是否正常都执行-->
<aop:after method="afterPrintLog" pointcut-ref="pt1" ></aop:after>
<!-- 配置切入点表达式:id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容
注意:此标签写在aop:aspect内部,只能当前切面使用
此标签写在aop:aspect外部,所有切面使用,注意:!!移到外面爆红了是要看引入约束的顺序,把这个移到前面就不报错啦
-->
<aop:pointcut id="pt1" expression="execution(* *..*.*(..))"/>
</aop:aspect>
</aop:config>
IOC(控制反转)就是依赖倒置原则的一种代码设计思路。就是把原先在代码里面需要实现的对象创建、对象之间的依赖,反转给容器来帮忙实现。
Spring IOC容器通过xml,注解等其它方式配置类及类之间的依赖关系,完成了对象的创建和依赖的管理注入。实现IOC的主要设计模式是工厂模式。
AOP(面向切面)是一种编程范式,提供从另一个角度来考虑程序结构以完善面向对象编程(OOP)。AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性
写在最后:AOP切面开发:解决代码,实例化,以及业务改动带来的全局影响,全称:降低耦合性 ,提高内聚性;
IOC开发:注解开发,我们声明一个接口,给一个持久层注解,注入到IOC容器,然后我们在接口里声明方法,在方法上给注解,用注解配合标签去实现sql,Java的解析器解析的内容是一样的,但优点在于模块化,跟别的接口 、别的方法关系不大,并且我们不需要去写映射,自动映射到实体类。
多总结