1.Spring优势
- 方便解耦:Spring提供的IoC容器,将对象间的依赖关系交给了Spring控制
- AOP编程支持:面向切面编程,传统的OOP(面向对象编程)难以实现的功能可以通过AOP实现
- 声明式事务管理
- 方便集成其他框架
- 降低Java EE API使用难度:不再需要手动配置Util包(JDBC、JavaMail…)
2.Spring 体系结构
- 层层递进的模式(除了最下层的Test,其他的要实现必须借助下面的技术)
- Test:表示框架整体都可以进行测试
- Core Container:核心容器,Beans–产生对象,Core–核心,Context–Spring上下文,spEL–Spring表达式语言
- AOP:面向切面编程
- Darta Access:数据访问层
- Web:Web层
3.Spring核心概念
- IoC:控制反转,是因为Spring将对象的控制权转到外部了,IoC容器负责对象的创建与初始化
- DI:依赖注入,在IoC容器中建立Bean之间的依赖关系
- 控制反转与依赖注入实现:
4.Spring入门
maven导入spring->创建bean->创建applicationContext.xml管理bean->在配置文件中配置bean->获取applicationContext对象getBean获取配置好的对象
5.Spring配置文件
小结:bean标签,id,class构造对象,property对对象赋值完成DI依赖注入(set注入)
1.bean标签
1.属性
- id:标签唯一标识
- class:bean的来源,值是类的全限定名,用于底层反射调用无参构造方法构建对象
- scope:对象的作用范围
- singleton:默认值,单例
- 对象将在加载配置文件时创建
- **应用卸载,**销毁容器后才被销毁
- prototype:多例,设置后每次获取的都是新的对象
- 对象将在配置文件对象getBean时创建
- 长时间不使用会被Java垃圾回收器回收
- request:WEB环境中,对象存入request域
- session:WEB环境中,对象存入session域
- singleton:默认值,单例
- init-method:指定初始化方法名
- destory-method:指定销毁方法名
<bean id="beanName" class="com.pb.dao.Userdao" scope="singleton"
init-method="init" destory-method="destory" />
2.bean实例化
- 构造bean对象(ioc):
- 默认无参构造:bean类的全限定名
- 工厂静态方法构造(因为静态方法在类上,可以直接调用):工厂类的全限定名+factory-method
- 工厂实例方法构造(必须先有工厂类的对象才能调用上面的实例方法):先factory的bean,然后目标bean上factory-bean+factory-method
// 默认无参构造
<bean id="beanName" class="com.pb.dao.Userdao" />
// 工厂静态方法构造
<bean id="factoryName" class="com.pb.factory.staticFactoty" factory-method="getObj" />
// 工厂实例方法构造
<bean id="factoryName2" class="com.pb.factory.Factory" />
<bean id="beanName" factory-bean="factoryName2" favtory-method="getObj2" />
3.DI依赖注入与分模块开发
- 依赖注入:Spring容器继夺走对象创建权后,通过依赖注入可以完成对单个对象的属性编写和bean间关系绑定
- 有两种注入方法,分别是set注入和有参构造注入,常用前者注入,但无论是哪种注入,bean实体内均要有对应的方法(set,constractor)
- 注入数据类型分三个,分别是引用数据类型(ref),普通数据类型,集合数据类型
- 配置项属性中,name对应实体类中属性名
- 分模块开发:配置项多且杂后,可以按功能分出多个xml配置文件,通过****来引入分配置文件
<!-- 有参构造注入 -->
<!-- java中有对应的有参构造方法
public UserServiceImpl(UserDaoImpl userDao) {
this.userDao = userDao;
} -->
<bean id="beanName" class="com.pb.dao.Userdao">
<constructor-arg name="userDao" ref="userDao"/>
</bean>
<!-- 常用的还是set注入 -->
<!-- 01.set注入普通属性(普通数据类型) name,value -->
<bean id="userDao" class="com.pb.dao.impl.UserDaoImpl">
<property name="name" value="张三" />
</bean>
<!-- 02.set注入引用类型数据 name,ref-->
<bean id="userService" class="com.pb.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao" />
</bean>
<!-- 03.set注入集合类型数据 list:value;
map:entry,key,value/value-ref;
props:prop
java中:
@Data
private ArrayList<String> list;
private HashMap<String,UserDao> map;
private Properties properties;-->
<bean id="jihe" class="com.pb.xxx">
<property name="list">
<list>
<value>aaa</value>
<value>aaa</value>
<value>aaa</value>
</list>
</property>
<property name="map">
<map>
<entry key="k1" value-ref="userDao"/>
<entry key="k2" value-ref="u2"/>
</map>
</property>
<property name="properties">
<props>
<prop key="p1">1</prop>
<prop key="p2">2</prop>
<prop key="p3">3</prop>
</props>
</property>
</bean>
2.两个API
1.获取配置文件对象
重点还是用第一个方法去new
2.获取bean对象
- 第一种:根据id去get,可以获取同一个类的不同实例bean对象,但需要强转
- 第二种:根据类的字节码文件去get,但不能获取同一个类的不同实例bean,不需要加强转
3.数据源(连接池)配置文件
数据源作用:提高程序性能,其原理同线程池,常用的有c3p0,druid
数据源配置文件:将字符串与代码解耦
1.抽取配置数据(手动)
作用:将要配置在数据库连接池中的数据提取出来单独配置,以达到解耦的目的
//1.读取properties文件的内容
Properties properties=new Properties();
//2.通过字节输入流读取properties文件的内容
FileInputStream in = new FileInputStream("完整路径.properties");
//3.加载properties文件
properties.load(in);
//先将配置文件放入静态资源文件夹resources中
ResourceBundle rb = ResourceBundle.getBundle("配置文件名");
String xxx = rb.getString("keyName")
2.Spring配置数据源
- 将datasource的创建权交由Spring容器完成,通过bean标签完成datasource的无参构造,再进行简单的普通属性注入(set注入)
- 配置文件交由spring容器处理
<!-- 复制bean的所有配置,将其中的bean改为context即可 -->
<!-- 命名空间 -->
xmlns:context="http://www.springframework.org/schema/context"
<!-- 约束路径 -->
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<!-- 将配置文件交由Spring命名空间 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
配置文件交由spring后,spring容器内会出现许多键值对,可以**直接通过SpEL表达式${}**获取对应的值<br />**关于classpath**:通过classpath定义文件路径,Spring容器将**直接在类目录下寻找配置文件**,不必使用硬编码的路径,增强了代码的可维护性<br />![image.png](https://cdn.nlark.com/yuque/0/2023/png/34797817/1686373805605-8f836841-0619-4a47-b15b-84fb53395b29.png#averageHue=%23192536&clientId=u59629b41-7d8f-4&from=paste&height=230&id=ue94b3e4d&originHeight=287&originWidth=1426&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=54898&status=done&style=none&taskId=uaddb96ff-a6f1-4afc-93e6-aa060e91352&title=&width=1140.8)
6.注解
作用:是为了替代xml配置(ssm开发是一个轻代码重配置的开发过程,为了减轻配置的繁重,就有了注解)
1.原始注解
用于替代bean标签配置
- @Component:在类上实例化Bean
- @Controller:controller层的@Component
- @Service:service层的@Component
- @Respository:dao层的@Component
- @Autowired:根据类型名依赖注入
根据接口名依赖注入但是注入的是接口的实例化bean?
在Spring中,一个接口通常是由一个或多个具体类来实现的。
当我们在配置文件中定义一个接口的bean时,Spring会在容器中查找该接口实现类的bean进行实例化,所以我们一般都直接定义接口的一个具体实现类的bean
但是,当我们使用@Autowired注解时,Spring会根据类型来查找对应的bean进行自动注入。**这里的类型可以是接口类型,也可以是具体类类型。**如果有多个bean符合类型要求,Spring会根据一定的规则来选择最合适的一个进行注入。
因此,**虽然我们注入的是接口类型,但是Spring会自动找到其实现类的bean进行注入。 **
- @Qualifier:(一个类型有多个实例bean时),配合@Autowired使用,根据名称依赖注入
- @Resource:组合注解,等同于@Autowired+@Qualifier
- @Value:普通属性注入【更广的应用:在Spring容器内引入配置文件后,可以配合SpEL注入配置文件内的value】
- @Scope:作用于类上,规定bean的作用范围
- @PostConstruct:作用于方法上,标注bean实例的init方法
- @PreDestory:作用于方法上,标注bean实例的destory方法
配置注解要告诉spring容器,开启组件扫描
<context:component-scan base-package="com.pb"/>
2.新注解–一般用在springboot集成了ssm的时候
用于解决原始注解无法替代的xml
- @Configuration:表示当前类是Spring的核心配置类,即最大的那个配置文件,当Spring创建容器时会从该类上加载注解
- @ComponentScan:开启组件扫描,内部的值即要扫描的基础包名
- @Bean:自定义的Bean
- @PropertySource:加载.properties配置文件
- @import:引入其他配置文件
// 核心配置类
//该类为Spring核心配置类
@Configuration
//<context:component-scan base-package="com.pb"/>
@ComponentScan("com.pb")
//<import resource="xxx.xml" />
@Import({DatasourceConfiguration.class,xxx.class,...})
// 分配置类
//<context:property-placeholder location="classpath:jdbc.properties"/>
@PropertySource("classpath:jdbc.properties")
public class DatasourceConfiguration {
@Bean("datasource")//值为为Bean的id
public DataSource getDatasource(){
// xxx
}
}
- 新的核心配置类用AnnotationConfigApplicationContext(xxx.class)接收
7.Spring集成
1.集成Junit4进行测试
**集成目的:**让Junit4帮我们创建Spring容器和DI注入需要测试的Bean实例对象
集成步骤:
集成实现:
// 1.pom.xml中导包
/*<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>*/
// 2.集成实现
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JunitTest {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.save();
}
}
2.集成web环境进行开发
1.手动管理应用上下文
详见一些思考-2-一个优化过程(监听器创建应用上下文并存入域对象->一次解耦(全局参数)->二次解耦(方法封装))
2.Spring管理应用上下文
完成的就是上述手动管理应用上下文的一系列封装(到最后的方法体封装)
所以我们要做的只有两个了:配置监听器和调用方法,其中配置监听器要先导包Spring-web,然后配置