Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
IOC(控制反转)主要解决的是程序间的耦合问题。高内聚、低耦合一直是所有程序员追求的最高境界。但是程序之间的依赖无法避免,我们只能倾其所学去降低程序之间的耦合度。Spring运用的工厂模式就体现了广大程序员为降低耦合度所做出的不懈努力。
IOC的思想就是由我们本来主动new一个对象变成工厂创建所有的对象放到容器里,当需要的时候去容器中调用。那么这么做真的会降低耦合度吗? 现在我们就来分析一下:按照MVC设计模式来开发一个项目,service层需要依赖dao层,web层需要依赖service层。使用new创建对象时,现在假如dao层的类消失了,依然运行项目的时候,由于没有dao层的对象,service层在编译阶段就会报错。使用工厂模式创建对象,我们新建对象时只需要传入对象的名称即可,这个时候需要的参数就是一个字符串。依旧是dao层对象消失,这个时候启动项目的话,最起码编译阶段不会报错,只有在运行阶段,工厂根据配置文件按照反射的原理创建对象时,才会报空指针异常。这个例子说明了使用工厂模式确实能够大大的降低耦合性。
一、Spring入门之IOC(配置文件开发)
1、获取配置文件的三个常用实现类的区别:
a、ClassPathXmlApplicationContext:加载类路径下的配置文件,不在类路径下加载不了。
b、FileSystemXmlApplicationContext:可以加载磁盘路径下的配置文件,绝对路径。
c、AnnotationConfigApplicationContext:读取注解创建容器。
2、核心容器的两个接口
a、ApplicationContext:在创建核心容器时,创建对象采用的策略是立即加载方式,即为一读取配置文件就立马创建配置文件的所有对象。
b、BeanFactory:在创建核心容器时,创建对象采用的策略是延迟加载方式,即为何时根据id获取获取对象,什么时候创建对象。
3、Bean作用范围的调整
bean标签的scope属性用来指定bean的作用范围。取值:
singleton:单例模式(默认值)
prototype:多例
request:作用于web应用的请求范围
session:作用于web应用的会话范围
global-session:作用于集群环境的会话范围(全局会话范围),不是集群环境时,范围与session相同。
4、Bean对象的生命周期
多例对象:
- 出生:当使用时,Spring容器为我们创建
- 活着:只要使用就一直活着
- 死亡:容器销毁,对象死亡
- 总结:长时间不用时,Java的垃圾回收机制就会回收对象
单例对象:
- 出生:容器创建时对象出生
- 活着:只要容器还在,对象一直活着
- 死亡:容器销毁,对象死亡
- 总结:单例对象的生命周期与容器相同
5、DI(依赖注入)
概念:在当前类需要用到其它类对象时,有Spring为我们提供。我们只需要在配置文件中说明依赖关系即可。
能注入的数据有三类
- . 1、基本类型与String
- . 2、其他Bean类型
- 3、复杂类型/集合
注入的方式有三种
- 1、使用构造函数提供
<bean id="account" class="com.runze.domain.Account">
<constructor-arg name="name" value="lihua"></constructor-arg>
<constructor-arg name="id" value="20"></constructor-arg>
<constructor-arg name="birthday" ref="birthday01"></constructor-arg>
</bean>
<bean id="birthday01" class="java.util.Date"></bean>
- 2、使用set方法提供
<bean id="account" class="com.runze.domain.Account">
<property name="name" value="zhaoziyi"></property>
<property name="id" value="32"></property>
<property name="birthday" ref="birthday01"></property>
</bean>
<bean id="birthday01" class="java.util.Date"></bean>
注入集合类型
<property name="lists">
<array>
<value>lihua</value>
<value>wangeu</value>
</array>
</property>
<property name="sets">
<set>
<value>zhaosi</value>
<value>zhaoziyi</value>
</set>
</property>
<property name="maps">
<map>
<entry key="1">
<value>yi</value>
</entry>
<entry key="2">
<value>er</value>
</entry>
</map>
</property>
- 3、使用注解
使用构造函数注入: - List item
二、Spring入门之IOC(注解开发)
1、用于创建对象的注解
首先需要在配置文件中设置要扫描是否有注解的包,Spring会到设置的包下扫描注解,如果有@Component注解,创建该对象存入容器中。
<?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">
<!--使用注解开发,编译时需要扫描的包,根据注解创建对象-->
<context:component-scan base-package="com.runze"></context:component-scan>
</beans>
```java
注解的配置
@Component("account")
@Controller
@Service
@Repository
上面三个注解分别放在表现层,业务层与持久层,与@Component功能一样
2、用于注入数据的注解
@Autowired:自动按照类型注入,只要容器中有一个唯一的Bean对象类型与要注入的变量类型匹配,就可以注入成功。如果ioc容器中没有Bean的类型与要注入的变量类型相同。则报错。如果容器中有多个bean的类型与要注入的变量类型相同,就使用另一个注解 @Qualifier用来指定要注入的bean对象的id。
@Autowired
@Qualifier(value = "accountDao1")
使用Resource可以取代以上两个注解
@Resource(name = "accountDao2")
以上三个注解只能注入bean类型的数据。基本类型和String类型使用value注解实现。集合类型只能通过xml来实现。
3、改变作用范围的注解
@Scope("singleton")
@Scope("prototype")
4、Spring中的新注解(使用SpringConfiguration代替bean.xml时,使用下面注解)
spring中的新注解
Configuration
- 作用:指定当前类是一个配置类
- 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
ComponentScan
- 作用:用于通过注解指定spring在创建容器时要扫描的包
- 属性:
value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
我们使用此注解就等同于在xml中配置了:
<context:component-scan base-package="com.itheima"></context:component-scan>
Bean
- 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
- 属性:
- name:用于指定bean的id。当不写时,默认值是当前方法的名称
- 细节:
当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。查找的方式和Autowired注解的作用是一样的
Import
- 作用:用于导入其他的配置类
- 属性:
- value:用于指定其他配置类的字节码。
当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
PropertySource
- 作用:用于指定properties文件的位置
- 属性:
- value:指定文件的名称和路径。
关键字:classpath,表示类路径下
二、Spring入门之AOP(XML开发)
开发步骤:
1、把通知Bean也交给spring来管理
2、使用aop:config标签表明开始AOP的配置
3、使用aop:aspect标签表明配置切面
id属性:是给切面提供一个唯一标识
ref属性:是指定通知类bean的Id。
4、在aop:aspect标签的内部使用对应标签来配置通知的类型。我们现在示例是让printLog方法在切入点方法执行之前之前执行
method属性:用于指定Logger类中哪个方法是前置通知
pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强
切入点表达式的写法:
关键字:execution(表达式)
execution需要写通配符。通配符的写法不太常用,省略。
<?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">
<!--配置AccountSercvice实现类的对象-->
<bean id="accountService" class="com.runze.service.Impl.AccountServiceImpl"></bean>
<!--spring中基于xml的aop配置
1、将通知类也配置到ioc容器中
2、使用aop:config表示来时aop配置
-->
<bean id="logger" class="com.runze.utils.Logger"></bean>
<aop:config>
<aop:aspect id="logAdvice" ref="logger">
<!--前置通知-->
<aop:before method="before" pointcut="execution(* com.runze.service.Impl.AccountServiceImpl.*(..))"></aop:before>
<!--后置通知-->
<aop:after-returning method="afterReturning" pointcut="execution(* com.runze.service.Impl.AccountServiceImpl.*(..))"></aop:after-returning>
<!--异常通知-->
<aop:after-throwing method="afterThrowing" pointcut="execution(* com.runze.service.Impl.*.*(..))"></aop:after-throwing>
<!--最终通知-->
<aop:after method="after" pointcut="execution(* com.runze.service.Impl.*.*(..))"></aop:after>
</aop:aspect>
</aop:config>
</beans>
三、Spring入门之事务控制(XML开发)
先放这。。。。