Spring
核心技术点: ioc di aop 声明式事务
ioc的底层实现(理解)
spring提供的ioc技术帮助我们解决了程序的高耦合问题,让我们不再花费时间去关心程序的高耦合
耦合:在编程语言中,就是计算机代码之间的依赖关系
代码之间的依赖关系如果很高就意味着程序高耦合,不利于后期项目的扩展开发,因此我们需要给程序松耦合
高耦合—松耦合–低耦合
需求 :自定义ioc的代码,实现更加松耦合的程序
代码实现:
- webTest
public class webTest {
@Test
public void test2() throws Exception {
UserService userService1= (UserService) Factory2.getBean("userService");
System.out.println(userService1);
}
}
- 单例工厂
package cn.itcast.utils;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
public class Factory2 {
private static ResourceBundle bundle=null;
private static Map<String,Object> map=new HashMap();
static {
try {
bundle=ResourceBundle.getBundle("bean");
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()){
String key = keys.nextElement();
String value = bundle.getString(key);
Class clazz = Class.forName(value);
Object obj = clazz.newInstance();
map.put(key,obj);
}
}catch (Exception e){
e.printStackTrace();
}
}
public static Object getBean(String id) throws Exception {
Object obj = map.get(id);
return obj;
}
}
4)多例工厂
package cn.itcast.utils;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
public class Factory {
private static ResourceBundle bundle=null;
private static Map<String,Object> map=new HashMap();
static {
bundle=ResourceBundle.getBundle("bean");
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()){
String key = keys.nextElement();
String value = bundle.getString(key);
map.put(key,value);
}
}
public static Object getBean(String id) throws Exception {
String value =(String) map.get(id);
Class clazz = Class.forName(value);
Object obj = clazz.newInstance();
return obj;
}
}
5)UserService
public interface UserService {
}
- UserServiceImpl
public class UserServiceImpl implements UserService {
}
- application.xml
<beans>
<bean id="userService" class="cn.itcast.serviceImpl.UserServiceImpl"></bean>
</beans>
结论
通过以上的配置文件+反射+工厂的方式可以实现程序解耦合,而spring的底层封装的就类似这一套的实现(ioc)
一 认识Spring的ioc容器
ioc:控制反转
指的是对象的控制权由原来开发者在类中自己手动创建控制 反转到 由Spring/ioc容器创建控制
其实spirng底层已经做好了工厂,这个工厂就已经帮助我们创建好了对象,放入到ioc容器中(就是map集合)
ioc作用
帮助咱们创建管理对象,做到程序之间的解耦合
获取对象方式:
传统方式获取对象:主动出击 new
Spring方式获取对象:问ioc容器要对象
二 Spring概述【了解】
Spring是分层的 Java SE/EE应用 full-stack 开源框架。以 IOC(Inverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
简单说:spring为三层开发提供了一站式的解决方案
web层: servlet---->springMvc框架
service层:声明式事务 --->事务
dao层:jdbc---->jdbcTemplate (企业多用mybits)
友情提示 spring课程的学习侧重点:ioc技术(DI) aop技术 声明式事务技术
spring的体系结构图
三 Spring的ioc快速入门【重点】
环境搭建
1 导入依赖
spring坐标依赖 要求junit4.12及以上版本
2 将对象的创建和管理交给spring容器
xml配置文件
3 从spring容器中获取对象
java代码的API调用
1)spring的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
- Demo2
public class Demo2 {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("application.xml");
UserService userService =(UserService)context.getBean("userService");
userService.save();
}
}
- application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="cn.itcast.serviceImpl.UserServiceImpl"></bean>
</beans>
流程图
四 Spring相关API【理解】
实现类
* FileSystemXmlApplicationContext【了解】
功能:从指定磁盘目录加载xml配置文件,创建spring的ioc容器
------------------------------------------
* ClassPathXmlApplicationContext (加载配置文件的)
功能:从类路径下加载xml配置文件,创建spring的ioc容器
* AnnotationConfigApplicationContext (加载注解的)
功能:加载注解配置类,创建spring的ioc容器
方法
1. public Object getBean(String id) throws BeansException; (掌握)
功能:通过指定id获取对象的实例,需要手动强转
2. public <T> T getBean(Class<T> requiredType);
功能:通过指定类型获取对象的实例,不需要强转
注意:同一个类型下只能有一个对象实例
五 Spring配置文件【重点】
5.1 Bean标签
配置信息
bean标签:指定创建对象的
id属性:唯一标识(配置文件中唯一)
class属性:实现类的全限定名
scope属性:范围
取值:singleton(单例默认) prototype(多例) 扩展:request,session,globesession..
singleton:对象是随着容器的创建而创建 随着容器的销毁而销毁 自始至终只有一个对象
prototype:对象的创建和销毁与容器的创建和销毁无关
每次执行getBean的时候创建新的对象 调用一次创建一次
销毁是会等待垃圾回收机制自动完成的
init-method属性: 对象创建之后指定调用方法
destroy-method属性:对象销毁后指定调用方法
5.2 spring创建对象实例三种方式
1.构造方式(重要)
2.静态工厂: 该工厂中获取对象的方法是静态的 可以类名直接调用(了解)
3.实例化工厂:该工厂中获取对象的方法是非静态的 必须得有工厂对象才能调用方法(了解)
1)构造方法实例化【重点】
<bean id="userService" class="cn.itcast.serviceimpl.UserServiceImpl"></bean>
2)工厂静态方法实例化【了解】
public class Factory {
public static Object getBean(){
return new UserServiceImpl();
}
}
<bean id="userService" class="cn.itcast.utils.Factory" factory-method="getBean"></bean></bean>
3)工厂普通方法实例化【了解】
public class Factory2 {
public Object getBean(){
return new UserServiceImpl();
}
}
<bean id="factory" class="cn.itcast.utils.Factory2"></bean>
<bean id="userService" factory-bean="factory" factory-method="getBean"></bean>
六 Bean依赖注入概述(掌握)
依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。
? 在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是对象的属性应该如何管理,这里spring
提供了技术:依赖注入
依赖注入:对存在依赖关系的属性或者对象自动赋值
属性分类:
注入简单数据类型的数据
注入复杂类型的数据(单列(array,list,set)和 双列(map,properties对象))
注入被spring容器管理的对象
依赖注入的两种方式:构造方法注入和set方法注入
Bean依赖注入方式
1)构造方法注入(了解)
public class UserServiceImpl implements UserService {
private String name;
private Integer age;
public UserServiceImpl(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public void save() {
System.out.println(name+":"+age);
}
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
<bean id="userDao" class="cn.itcast.daoimpl.UserDaoImpl"></bean>
<bean id="userService" class="cn.itcast.serviceimpl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
2)set方法注入【重点】
public class UserServiceImpl implements UserService {
private String name;
private Integer age;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public void save() {
System.out.println(name+":"+age);
}
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
private Set<Object> arr;
public void setArr(Set<Object> arr) {
this.arr = arr;
}
@Override
public void save() {
System.out.println(arr);
}
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public void save() {
System.out.println(properties);
}
private Map<String,Object> map;
public void setMap(Map<String, Object> map) {
this.map = map;
}
@Override
public void save() {
System.out.println(map);
}
}
<bean id="userDao" class="cn.itcast.daoimpl.UserDaoImpl"></bean>
<bean id="userService" class="cn.itcast.serviceimpl.UserServiceImpl">
<property name="name" value="jack"></property>
<property name="age" value="18"></property>
<property name="userDao" ref="userDao"></property>
<property name="arr">
<set>
<value>abc</value>
<ref bean="userDao"></ref>
</set>
</property>
<property name="map">
<map>
<entry key="key1" value="abcd"></entry>
<entry key="key2" value-ref="userDao"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
</bean>
七、Spring注解开发
? Spring是轻代码而重配置的框架,配置比较繁重,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
spring的开发方式:
1 全xml方式
特点:所有配置都在xml配置文件中
2 半xml半注解方式
特点:一半使用的是配置文件(第三方) 一半使用的是注解(自己的资源)
3 全注解方式
特点:所有配置全部用注解
spring--全注解(半成品(理解))--springboot(成品 企业开发趋势)--项目一,二
案例:使用spring操作account表做添加(全xml方式 半xml半注解方式 全注解方式)
1.1 spring的半xml和半注解式开发
半xml半注解式:一般我们会将自己的资源用注解代替 第三方资源继续保留XML方式
条件:spring的注解默认是关闭的 需要在xml中配置一个注解扫描器开启注解
开启注解扫描器:<context:component-scan base-package="cn.itcast"></context:component-scan>
注解扫描器的作用:告诉spring去哪些包(包含子包)下解析编写好的注解
使用到的注解概述
ioc:控制反转(将对象交给spring创建管理)
@Component
@Controller
@Service
@Repository
特点:被扫描到后,后将被自己注解的类创建对象 放在ioc容器中
1.需要配置到类上
2.默认不配置标识该对象在spring容器中的唯一标识:就当前类名首字母小写
3.如果配置标识:可以用value指定唯一标识
DI:依赖注入(为spring管理的对象进行属性赋值)
@Autowired
spring默认按照接口类型从容器中查找对象并注入 set属性可以省略不写
@Qualifier
取值 Value:用来指定唯一标识
按照指定的唯一标识从容器中查找对象并注入
特点:没办法单独使用 只能依附@Autowired一起出现
总结:
1 如果ioc中只有一个实现对象,就直接@Autowired
2 如果ioc容器中有多个实现对象,可以使用方式:
@Autowired+@Qualifier(指定id标识) (掌握)
了解:不用
JDK提供的依赖注入的注解
@Resource:按照唯一标识从容器中查找对象并注入
取值 Name:用来指定唯一标识
相当于@Autowired+@Qualifier
生命周期的注解(了解)
@Scope : 对象的作用域 配置在类上
Value属性(singleton| prototype)
@PostConstruct : 配置到方法上 init-method
配置初始化方法
@PreDestory:配置到方法上 destroy-method
配置销毁方法
半xml半注解的执行流程
1.2 spring的全注解式开发(理解)
全注解:自己编写的资源和第三方的资源都用注解方式
ps:该spring的全注解不是最终版 所以很麻烦 等到springboot在该基础做完优化 就是最终版了
条件:
1 使用配置类替换xml配置文件
创建一个类,使用注解申明是一个配置类
2 代码端不在加载配置文件,而是加载配置类
ApplicationContext context=new AnnotationConfigApplicationContext(配置类.class);
使用到的注解
@Configuration:声明配置类 可以省略不写
@ComponentScan: 开启包扫描
取值 basePackages:指定扫描的包
@PropertySource:将properties配置文件交给spring容器管理
取值 value:指定要加载的文件地址
@Bean : 配置到方法上,表明此方法的返回值交给spring容器管理
将第三方对象交给spring容器管理的时候使用@Bean
取值 value:指定在ioc容器中的id标识
@Value:用来取properties中的内容 但是只能设置在成员变量上 类似el表达式获取数据 ${jdbc.username}
@Import(从配置类的.class):引入从配置类
全注解的执行流程图
|