框架要学什么?
框架和类库的区别
框架的难度
框架的实现方式
Spring是一个开源的设计层面框架,于2003 年兴起的由Rod Johnson创建。Spring是一个分层的JavaSE/EE的一站式、轻量级、开源框架。
IOC(Inversion of Control):控制反转。降低了业务对象替换的复杂性,提高了组件之间的解耦。
AOP(Aspect Oriented Programming):面向切面编程。允许将一些通用任务(如安全、事务、日志等)进行集中式管理,从而实现更好的复用。
官网地址:https://spring.io/
类库下载:http://repo.spring.io/release/org/springframework/spring/
sts(spring tool suite):Spring 工具套件。它是一个基于Eclipse的开发环境, 用于开发Spring应用程序。它提供了一个现成的使用环境来实现调试、运行和部署你的Spring应用程序。包括为关键的的服务器和云计算,Git, Maven, AspectJ和最新的Eclipse版本提供整合支持。
各Eclipse版本的sts下载地址 : https://spring.io/tools/sts/legacy。
sts 在线安装:使用Eclipse Marketplace ,可直接搜索 sts 安装。
IOC(Inversion of Control)中文含义是控制反转。
当需要某个对象实例时,在传统的程序设计过程中,通常由调用者来创建该实例。但在Spring里,创建对象的工作由Spring来完成,因此称为控制反转。IOC 降低了业务对象替换的复杂性,提高了组件之间的解耦。
// Dao层接口
public interface UserDao {
void insert();
}
// Dao层实现类
public class UserDaoImpl implements UserDao{
@Override
public void insert() {
System.out.println("插入一条数据...");
}
}
//原始的方式
UserDao userDao = new UserDaoImpl();
userDao.insert();
原始方式就是手动实例化对象。如果项目中有10处使用 UserDao实例,则需要实例化10次对象。问题在于,当 UserDao的实现方式发生变化时(比如实现类是UserDaoImpl2),这10处位置都需要修改。
换句话说,组件之间的耦合性较高,业务对象替换的比较复杂。
把组件实例化过程交给工厂,需要实例化对象的时候,调用工厂类的方法统一处理。
public interface BeanFactory {
//根据id获得bean实例
Object getBean(String id);
}
根据全路径类名获得类的实例
通过反射机制,根据全路径类名,获得类的实例
/**
* 根据全路径类名获得类的实例
* 技术点:反射
* @param className 全路径类名
* @return 类的实例
* @throws Exception
*/
private Object getInstanceByClassName(String className) throws Exception{
//获得类的加载器
ClassLoader classLoader = getClass().getClassLoader();
//加载类
Class<?> cls = classLoader.loadClass(className);
//创建实例
Object obj = cls.newInstance();
return obj;
};
配置文件
在class 类路径下新建配置文件“application-config.xml”,统一对需要实例化的对象进行配置。
<beans>
<bean id="UserDao" class="com.bodhixu.ssm.UserDaoImpl"/>
beans>
读取并解析配置文件
读取配置文件,并通过dom4j进行解析。并通过反射生成实例,放入map集合
/**
* 读取配置文件,获得bean实例
* 技术点:dom4j
* @param xmlPath 配置文件路径
* @return bean的map集合
* @throws DocumentException
*/
private Map<String, Object> initConfig(String xmlPath) throws Exception {
Map<String, Object> beanMap = new HashMap<>();
//读取配置文件,获得输入流
InputStream is = getClass().getResourceAsStream(xmlPath);
//创建解析器
SAXReader reader = new SAXReader();
//加载数据,获得文档模型
Document doc = reader.read(is);
//获得文档根节点
Element rootElement = doc.getRootElement();
//获得所有bean的子节点
List<Element> beanElements = rootElement.elements("bean");
//遍历bean子节点
for (Element element : beanElements) {
//获得id属性
String id = element.attributeValue("id");
//获得class属性
String cls = element.attributeValue("class");
//根据类名获得类的实例
Object obj = getInstanceByClassName(cls);
//放入map集合
beanMap.put(id, obj);
}
return beanMap;
}
根据id获得bean实例
提供 get 方法,根据 id 返回 bean 对象
public Object getBean(String id) {
return beanMap.get(id);
}
BeanFactory:接口
ApplicationContext:接口
ClassPathXmlApplicationContext:实现类,加载类路径下的配置文件
FileSystemXmlApplicationContext:实现类,加载文件系统下的配置文件
<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="userDao" class="com.bodhixu.ssm.UserDaoImpl"/>
beans>
ApplicationContext context =
new ClassPathXmlApplicationContext("/application-config.xml");
UserDao userDao = (UserDao) context.getBean("UserDao");
DI(Dependency Injection)依赖注入,用来实现对bean对象属性赋值。
DI 的实现方式主要有构造器注入和 setter注入,另外其他一些方式如工厂方法注入(很少使用,不推荐)。
必须提供有参构造方法
<bean id="Book" class="com.bodhixu.ssm.demo01.Book">
<constructor-arg name="name" value="Java"/>
<constructor-arg name="price" value="200"/>
bean>
setter 注入
必须提供 setter 方法
<bean id="Book" class="com.bodhixu.ssm.demo02.Book">
<property name="name" value="Oracle"/>
<property name="price" value="200"/>
bean>
<bean id="book" class="com.bodhixu.ssm.demo03.Book">
<property name="name" value="Oracle"/>
<property name="price" value="200"/>
bean>
<bean id="student" class="com.bodhixu.ssm.demo03.Student">
<property name="name" value="小张"/>
<property name="book" ref="book" />
bean>
<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="book1" class="com.bodhixu.ssm.demo04.Book">
<property name="name" value="java"/>
<property name="price" value="100"/>
bean>
<bean id="book2" class="com.bodhixu.ssm.demo04.Book">
<property name="name" value="orcle"/>
<property name="price" value="200"/>
bean>
<bean id="Student" class="com.bodhixu.ssm.demo04.Student">
<property name="arr">
<array>
<value>arrItem1value>
<value>arrItem2value>
array>
property>
<property name="list">
<list>
<value>listItem1value>
<value>listItem2value>
list>
property>
<property name="set">
<set>
<value>listItem1value>
<value>listItem2value>
set>
property>
<property name="map">
<map>
<entry key="mapkey1" value="mapValue1" />
<entry key="mapkey2" value="mapValue2" />
map>
property>
<property name="books">
<list>
<ref bean="book1"/>
<ref bean="book2"/>
list>
property>
bean>
beans>
为了简化XML文件的属性配置,Spring从2.5后,引入了新的p命 名空间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0AmksVvj-1587633631341)(img/img7.png)]
xmlns:p="http://www.springframework.org/schema/p"
<bean id="Book" class="com.bodhixu.ssm.demo05.Book"
p:name="HTML" p:price="60"/>
SpEL(Spring Expression Language)Spring的表达式语言。
语法:#{SpEL}
<bean id="book1" class="com.bodhixu.ssm.demo06.Book">
<property name="name" value="Oracle"/>
<property name="price" value="200"/>
bean>
<bean id="book2" class="com.bodhixu.ssm.demo06.Book">
<property name="name" value="#{'new' + book1.getName()}"/>
<property name="price" value="#{200+20}"/>
bean>
Spring 中对 Bean 的管理有两种方式,一种是通过 xml 配置来管理,一种是通过注解来管理。
<context:component-scan base-package="com.bodhixu.ssm" />
<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-4.3.xsd">
<context:component-scan base-package="com.bodhixu.web.bean"/>
beans>
组件注解的类型
组件注解注释在类上,共有4个,他们作用一样,只是语义化了。暂时我们使用 @Component 注解,在后面的SrpingMVC 中会使用其他注解。
组件名称的设置
给组件注入名称相当于 xml 配置中的 id 属性,设置名称有3种方式。
@Component(value="book")
public class Book {}
@Component("book")
public class Book {}
@Component //名称默认是book
public class Book {}
使用 @Scope 可以设置Bean的作用域,作用同 xml 中配置 bean 的作用域一样。常用的有 singleton 单例模式和 prototype 多例模式。默认是单例的。
@Scope(value="prototype") //单一属性可以省略value=
使用注解注入属性,对象不需要setter方法。如果有setter方法,注解需要写在setter方法上。
@Component("book3")
public class Book {
@Value(value="java编程") //单一属性可以省略value=
private String name;
@Value("100")
private int price;
}
@Component("book4")
public class Book {}
@Component("stu1")
public class Student {
@Resource(name="book4")
private Book book;
}
@Repository
public class UserDao {
public void insert() {
System.out.println("UserDao insert...");
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void regist() {
userDao.insert();
}
}
class Test {
@org.junit.jupiter.api.Test
void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("/application-config.xml");
UserService service = (UserService) context.getBean("userService");
service.regist();
}
}