认识Spring
官网:https://spring.io/projects/spring-framework
官方下载地址:https://repo.spring.io/release/org/springframework/spring/
GitHub:https://github.com/spring-projects/spring-framework
需要导入的包有
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
Spring的优点
- Spring是一个开源的免费的框架(容器)
- Spring是一个轻量级的、非入侵式的框架
- 控制反转(IOC)、面向切面编程(AOP)
- 支持事务的处理,对框架整合的支持
Spring七大模块
-
Spring Code: 提供Spring框架的核心功能。它主要的组件就是BeanFactory,是工厂模式的实现。同时BeanFactory适用控制反转(IOC)思想将应用程序的配置和依赖性规范与实际的应用程序分开。
-
Spring Context: Spring上下文是一个配置文件,主要向框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。
-
SpringAop: 通过配置管理特性,SpringAOP模块直接将面向切面地编程功能集成到了Spring框架中,所以,它可以很容易地使Spring框架管理的任何对象支持AOP。SpringAOP模块也是基于Spring的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
-
SpringDAO: 它主要和dao层相关联,可以用该结构来管理异常处理和不同数据库供应商抛出的错误信息。其中异常层次结构简化了错误处理,并且极大地降低了需要编写地异常代码数据(例如打开和关闭连接)。
-
Spring ORM : Spring框架中插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
-
SpringWEB模块: Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
-
SpringMVC:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、FreeMarker、Velocity、Tiles(jsp布局)、iText(报表处理) 和 poi。
1、编辑xml配置文件
(IOC容器):applicationContext.xml
该文件的所有对象,被Spring放入了一个称之为SpringIOC容器的地方
1、创建对象
- 1、id:唯一标识符
- 2、class:指定类型
2、给对象的属性赋值
1、构造注入:constructor-arg
<bean id="student" class="com.sise.dao.student">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="18"/>
</bean>
value:按构造方法的参数顺序赋值
index=“0”、index=“1”。。。
2、set注入:property:该class代表的类的属性
<bean id="teacher" class="com.sise.dao.teacher">
<property name="name" value="李四"/>
<property name="studentName" ref="student"/>
</bean
name:属性名
value:属性值
ref:bean的id
set注入的几种方式:
<bean id="student" class="com.sise.dao.student">
<!--第一种方式-->
<property name="name"><value>ljx</value></property>
<!--第二种方式-->
<property name="age" value="23" />
<!--list注入-->
<property name="listValues">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<!--array注入-->
<property name="array">
<array>
<value>array1</value>
<value>array2</value>
</array>
</property>
<!--map注入-->
<property name="map">
<map>
<entry key="身份证" value="11111111111111111"/>
<entry key="银行卡" value="11111111111111111"/>
</map>
</property>
<!--set注入-->
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
</set>
</property>
<!--Prpperties-->
<property name="info">
<pros>
<prop key="driver">xxx</prop>
<prop key="url">xxx</prop>
<prop key="username">xxx</prop>
<prop key="password">xxx</prop>
</set>
</property>
</bean>
3、接口注入
3、bean的scope属性值
singleton(默认)、prototype、request、session、globalSession
4、初始化方法init-method
<bean init-method="方法名"/>
5、别名
可以取多个别名,可以用空格、逗号、分号分隔别名
<bean name="别名"/>
6、命名空间
<?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:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="teacher" class="com.sise.dao.teacher"/>
<!-- 通过set方法注入的传统的bean定义 -->
<bean id="student" class="com.sise.dao.student">
<property name="name" value="ljx"/>
<property name="age" value="23"/>
<property name="teacher" ref="teacher"/>
</bean>
<!-- 通过set方法注入的使用p命名空间的bean定义 -->
<bean id="student2" class="com.sise.dao.student" p:name="ljx" p:age="23" p:teacher-ref="teacher"/>
<!-- 使用c命名空间通过构造方法注入的bean定义 -->
<bean id="student3" class="com.sise.dao.student" c:name="张三" c:age"25" c:teacher-ref="teacher"/>
</beans>
7、Bean的自动装配
- 自动装配是Spring满足bean依赖的一种方式
- Spring会在上下文中自动寻找,并自动给bean装配属性
- 在Spring中有三种装配方式
1、在xml中显示的配置
2、在Java中显示的配置
3、隐式的自动装配bean
<bean id="dog" class="com.sise.autowire"/>
<bean id="cat" class="com.sise.autowire"/>
<!--byName:会自动在容器上下文中查找,和自己对象set的后面的值的对应bean的id作自动装配-->
<bean id="people" class="com.sise.autowire" autowire="byName">
<property name="ljx" value="ljx"/>
</bean>
<!--byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean,自己对象属性类型相同的bean的id值可省略(dog和cat)-->
<bean id="people2" class="com.sise.autowire" autowire="byType">
<property name="ljx" value="ljx"/>
</bean>
注意:byName只要保证与set后面的值一致就行,而byType需要该class的类型全局为1,也就是只能唯一
注:一个对象一个bean,获取ioc容器才能拿对象
2、容器初始化
1、创建Spring上下文对象context
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- 1.1 遇到多个配置文件时,可把参数改成
new String[]{"applicationContext1.xml","applicationContext2.xml"}
- 1.2 在一个主配置文件中导入多个配置文件
<import resource="applicationContext2.xml">
- 1.3 在一个配置文件中引用另一个配置文件的bean
<bean class="类路径">
注:会预先对bean定义文件的内容,将所有的bean实例化,如果不希望这样,则可以在bean上设置属性lazy-init为true,ApplicationContext就不会在启动时做实例化动作
2、资源文件的定位及容器初始化
Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory factory = new XmlBeanFactory("resource");
注:只有在使用getBean()方法真正取得bean时,才会做实例化的动作
3、通过getBean()获取bean对象的id
Student student = (Student) context.getBean("student");
“student”是<bean/
>中的id值
4、使用注解实现自动装配
jdk1.5支持的注解,Spring2.5就支持注解了
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.
要使用注解须知:
- 导入约束:context的约束
- 配置注解的支持
<context:annotation-config/>
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
- 可以在属性前添加,也可以在set方法前添加。
注意:使用@Autowired可以不用写set方法了,前提是你这个装配的属性在IOC(Spring)容器中,且符合名字byname - 如果显示定义了Autowired的属性required的值为false,说明这个对象可以为null,否则不允许为空。
@Nullable
- 字段标记了这个注解,说明这个注解可以为null
@Qualifier(value=“bean的id值”)
- 特指对应的bean的id
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个@Autowired完成的时候,我们可以使用Qualifier(value=“bean的id值”)去配合@Autowired的使用,指定一个唯一的bean的对象注入。
@Resource
- 首先会通过bean的id名字自动配置,找不到相同名字的id的时候再找class的类型,也可以使用@Resource(name=“bean的id值”)来唯一指定。
@Autowired与@Resource的区别
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired通过byType的方式实现,而且必须要求这个字段存在
- @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现,如果两个都找不到,就报错。
5、使用注解开发
1、在Spring4之后,要使用注解开发,必须要保证aop的包导入了
2、使用注解必须要导入context的约束,增加注解的支持:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 指定要扫描的包,这个包下的注解就很生效-->
<context:component-scan base-package="com.sise.dao"/>
<context:annotation-config/>
</beans>
3、属性的注入
package com.sise.dao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//相当于<bean id="person" class="com.sise.dao.Person">
@Component
public class Person {
//相当于<property name="name" value="ljx"/>
@Value("ljx")
public String name;
}
或者
package com.sise.dao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//相当于<bean id="person" class="com.sise.dao.Person">
@Component
public class Person {
public String name;
//相当于<property name="name" value="ljx"/>
@Value("ljx")
public void setName(String name) {
this.name = name;
}
}
4、衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao
@Repository
package com.sise.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
}
- service
@Service
package com.sise.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
}
- controller
@Controller
package com.sise.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
}
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配bean
5、作用域
package com.sise.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
@Controller
@Scope("singleton")
//singleton(默认)、prototype、request、session、globalSession
public class UserController {
}
6、xml与注解
- xml更加万能,适用于任何场合,维护简单方便
- 注解不是自己的类使用不了,维护相对复杂
7、xml与注解最佳实践
- xml用来管理bean
- 注解只负责完成属性的注入
6、使用Java方式配置Spring
我们现在要完全不使用Spring的xml来配置了,全权交给Java来做。
JavaConfig是Spring的一个子项目,在Spring4之后,它完全成为了一个核心功能。
实体类
package com.sise.dao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("ljx")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
配置类
package com.sise.config;
import com.sise.dao.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//这个也会被Spring容器托管,注册到容器中,因为它本来就是一个@Component
//@Configuration代表这是一个配置类,就和我们之前看的applicationContext.xml是一样的
@Configuration
@ComponentScan("com.sise")//等价于<context:component-scan base-package="com.sise"/>
@Import(MyConfig2.class)//引入另一个类
public class MyConfig {
//注册一个bean,相当于我们之前写的一个bean标签
//这个方法的名字,就相当于bean标签中的id
//这个方法的返回值,就相当于bean标签的class
@Bean
public User user(){
return new User();//返回要注入到bean的对象
}
}
测试类
import com.sise.config.MyConfig;
import com.sise.dao.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args){
// ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// User user = (User) context.getBean("user");
// System.out.println(user.getName());
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = (User) context.getBean("user");
System.out.println(user.getName());
}
}
输出结果
7、代理模式
1、代理模式的目的:
保护目标对象,增强目标对象
2、 角色分析
- 抽象角色:一般会使用接口或抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人
3、 代理模式的优缺点
优点
- 代理模式能将代理对象与真实被调用目标对象分离。
- 在一定程度上降低了系统的耦合性,扩展性好。
- 可以起到保护目标对象的作用。
- 可以增强目标对象的功能
缺点
- 代理模式会造成系统设计中类的数量的增加
- 在客户端和目标对象中增加一个代理对象,会导致请求处理速度变慢
- 增加了系统的复杂度