目录
prototype(原型模式) 每次从容器中get的时候,都会产生一个新对象!
Spring:春天------>给软件行业带来了春天!2002,首次推出了Spring框架的雏形: interface21框架!
Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。Rod Johnson ,Spring Framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!
官网: Spring Frameworkhttps://spring.io/projects/spring-framework/#overview官方下载地址:JFrog (spring.io)https://repo.spring.io/ui/native/release/org/springframework/springGitHub: (github.com)https://github.com/spring-projects/spring-framework
-
org.springframework -
spring-webmvc -
5.2.0.RELEASE -
org.springframework -
spring-jdbc -
5.2.0.RELEASE
Spring框架是由于软件开发的复杂性而创建的。Spring就是一个轻量级的控制反转((loa)和面向切面编程(AOP)的框架
优点
核心容器提供spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。BeanFactory使用依赖注入的方式提供给组件依赖。
Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。
通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring框架中。所以,可以很容易地使 Spring框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
DAO模式主要目的是将持久层相关问题与一般的的业务规则和工作流隔离开来。Spring 中的DAO提供一致的方式访问数据库,不管采用何种持久化技术,Spring都提供一直的编程模型。Spring还对不同的持久层技术提供一致的DAO方式的异常层次结构。
Spring 与所有的主要的ORM映射框架都集成的很好,包括hibernate、JDO实现、TopLink和IBatis SQL Map等。Spring为所有的这些框架提供了模板之类的辅助类,达成了一致的编程风格。
Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。Web层使用Web层框架,可选的,可以是Spring自己的MVC框架,或者提供的Web框架,如Struts、Webwork、tapestry和jsf。
MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。Spring的MVC框架提供清晰的角色划分:控制器、验证器、命令对象、表单对象和模型对象、分发器、处理器映射和视图解析器。Spring支持多种视图技术
因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!弊端:发展了太久之后,东西越来越多,违背了原来的理念!配置十分繁琐,人称:“配置地狱!”
原来传统的方式
1、先写一个UserDao接口
- public interface UserDao {
- public void getUser();
- }
2、再去写Dao的实现类
- public class UserDaoImpl implements UserDao {
- @override
- public void getUser(){
- System.out.print1n("获取用户数据");
- }
- }
3、然后去写UserService的接口
- public interface Userservice {
- public void getUser();
- }
4、最后写Service的实现类
- publig clacs UserserviceImpl implement Userservice {
- private UserDao userDao = new UserDaoImpl();
-
- @override
- public void getUser() {
- userDao.getUser();
- }
- }
5、测试一下
- @Test
- public void test(){
- UserService service = new UserServiceImpl();
- service.getUser();
- }
这是我们原来的方式,开始大家也都是这么去写的对吧
那我们现在修改一下把Userdao的实现类增加一个
- public class UserDaoMySqlImpl implements UserDao {
- @override
- public void getUser(){
- System.out.print1n("MySql获取用户数据");
- }
- }
紧接着我们要去使用MySql的话,我们就需要去service实现类里面修改对应的实现.
publig clacs UserserviceImpl implement Userservice {
private UserDao userDao = new UserDaoMySqlImpl();
@override
public void getUser() {
userDao.getUser();
}
}
在假设,我们再增加一个Userdao的实现类
- public class UserDaoOrscleImpl implements UserDao {
- @override
- public void getUser(){
- System.out.print1n("Orscle获取用户数据");
- }
- }
那么我们要使用Oracle,又需要去service实现类里面修改对应的实现
publig clacs UserserviceImpl implement Userservice {
private UserDao userDao = new UserDaoOracleImpl();
@override
public void getUser() {
userDao.getUser();
}
}
假设我们的这种需求非常大,这种方式就根本不适用了,甚至反人类对吧,每次变动,都需要修改大量代码﹒这种设计的耦合性太高了,牵一发而动全身.
那我们如何去解决呢?
我们可以在需要用到他的地方,不去实现它,而是留出一个接口,利用set,我们去代码里修改下
- publig clacs UserserviceImpl implement Userservice {
- private UserDao userDao;
-
- public void setUserDao(UserDao userDao){
- this.userDao = userDao;
- }
-
- @override
- public void getUser() {
- userDao.getUser();
- }
现在去测试类里,进行测试
- @Test
- public void test(){
- UsererviceImpl service = new UserServiceImpl();
- service.setUserDao(new UserDaoMySqlImpl());
- service.getUser();
- //那我们现在又想用Orical去实现呢
- service.setUserDao(new UserDaoOracleImpl());
- service.getUser();
- }
仔细去思考一下,以前所有东西都是由程序去进行控制创建,而现在是由我们自行控制创建对象,把主动权交给了调用者,程序不用去管怎么创建,怎么实现了,它只负责提供一个接口
这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。系统的耦合性大大降低~,可以更加专注的在业务的实现上!这是IOC的原型!
------->
控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现loC的一种方法,也有人认为DI只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
loC是Spring框架的核心内容,使用多种方式完美的实现了loC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现loC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从loc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,Dl)。
1、pojo文件夹下创建 Hello类
- public class Hello {
- private String str;
-
- public string getstr() {
- return str;
- }
- public void setstr(String str) {
- this.str = str;
- }
- @Override
- public String toString() {
- return "He1lo{"+
- "str='" +str + '\''+
- '}';
- }
- }
2、在resources文件夹下,创建applicationContext.xml文件
- "1.8" encoding="UTF-8"?>
"http: //www.springframework.org/schema/beans" - xmlns:xsi="http: //www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- https://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
-
"hello" class="com.pojo.Hello"> -
"str" value="Spring"/> -
-
3、在test文件夹下创建测试类
- @Test
- public void test (){
- //解析beans.xml文件,生成管理相应的Bean对象
- ApplicationContext context = newClassPathXm1lApplicationcontext("beans.xml");
- //getBean :参数即为spring配置文件中bean的id
- Hello hello = (Hello)context.getBean("hello");
- hello.show ();
- }
思考问题?
这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的
反转∶程序本身不创建对象,而变成被动的接收对象
依赖注入︰就是利用set方法来进行注入的
IOC是一种编程思想,由主动的编程变成被动的接收
可以通过newClassPathXmlApplicationContext去浏览一下底层源码
到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的loC,一句话搞定:对象由Spring 来创建,管理,装配!
之前例子改写,用xml实现
- "1.0"encoding="UTF-8"?>
"http: / /www.springframework.org/schema/beans" - xmlns:xsi="http: //www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- https://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
"mysqlImpl" class="com.dao.UserDaoMysqlImpl" /> -
"oracleImpl" class="com.dao.UserDaoOracleImpl"/> -
"UserServicelmpl" class="com.kuang.service.UserServiceImpl"> -
-
"userDao" ref="mysqlImpl"/> -
测试不用再new了
- public class MyTest {
- public static void main( String[] args) {
- //获取Applicationcontext;拿到Spring的容器
- ApplicationContext context = new classPathXmlApplicationContext("beans.xml");
- //容器在手,天下我有,需要什么,就直接get什么!
- UserServiceImpl userServiceImpl = (UserServiceImpl)
- context.getBean("UserServiceImpl");
- userServiceImpl.getUser();
- }
POJO----User
- public class User {
- private String name;
-
- public User(){
- System.out.println("User的无参构造!");
- }
-
- public string getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public void show(){}
- System.out.println("name="+name);
- }
- }
resources----->beans.xml
- "1.0" encoding="UTF-8"?>
"http://www.springframework.org/schema/beans" - xmlns:xsi="http: //www.w3.org/20日1/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- https://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
"user" class="com.pojo.User"> - property name="name" value="花花"/>
-
test--->MyTest测试类
- public class MyTest {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicat ionContext("beans.xml");
- User user = (User) context.getBean("user");//User的无参构造!
- user.show();//name=花花
- }
- public class User {
- private String name;
-
- public User(String name){
- this.name=name;
- }
-
- public string getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public void show(){}
- System.out.println("name="+name);
- }
- }
"user" class="com.pojo.User"> -
"0" value="花花"/>
"user" class="com.pojo.User"> -
"java.lang.String" value="花花"/>
"user" class="com.pojo.User"> -
"name" value="花花"/>
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
-
"user" alias="userNew"/>
- id : bean 的唯一标识符,也就是相当于对象名
- class : bean对象所对应的全限定名:包名+类型
- name :也是别名,而且name 可以同时取多个别名 空格,;都可识别
"user" class="com.pojo.User" name="user2 u2,u3;u4"> -
"name" value="花花"/>
(3)import
这个import, 一般用于团队开发使用,他可以将多个配置文件,导入合并为一个。假设,现在项目中有多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
●张三beans. xml
●李四beans2. xml
●王五beans3. xml
applicationContext.xml
- <import resource="beans.xml"/>
- <import resource="beans2.xml"/>
- <import resource="beans3.xml"/>
使用的时候,直接使用总的配置applicationContext.xml就可以了
六、依赖注入
(1)构造器注入
前面已经说过了
(2)Set方式注入【重点】
●依赖注入: Set注入!
依赖: bean对象的创建依赖于容器!
注入: bean对象中的所有属性,由容器来注入!
【环境搭建】
1.复杂类型
- public class Address {
- private String address;
- get set tostring...
- }
2.真实测试对象
- public class Student {
- private String name;
- private Address address;
- private String[] books;
- private List
hobbys ; - private Map
card; - private Set
games; - private String wife;
- private Properties info;
-
- get set tostring 省略.....
- }
3.beans.xml
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
ref="花花"/>
红楼梦
西游记
水浒传
三国演义
array>
< !--List-->
听歌
敲代码
看电影
list>
< ! --set-->
LOL
coc
BOB
< !--null-->
< ! --Properties-->
eeffgggh
afdsv
root
123456
4.测试类
- public class MyTest {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicat ionContext("beans.xml");
- Studentr student = (Student) context.getBean("student");
- System.out.println(student.toString());
- }
(3)拓展方式
官方文档Core Technologies (spring.io)
User类
public class User {
private String name;
private int age;
public User(){}
public User(string name,int age) {
this.name = name;
this.age = age;
}
get set tostring.....
}
userbeans.xml
- "1.0" encoding="UTF-8"?>
"http://www.springframework.org/schema/beans" - xmlns:xsi="http: //www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www .springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- https://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
-
"user" class="com.pojo.User" p:name="花花" p:age="18"/> -
-
-
"user2" class="com.pojo.User" c:age="18" c:name="西西" /> -
测试
@Test
public void test2(){
Applicationcontext context = new classPathxmlApplicationContext("userbeans.xml");
User user = context.getBean("user2",User.class);//不用强制类型转换了
System.out.println(user);
}
注意点:p命名和c命名空间不能直接使用,需要导入xml约束!
xmlns :c="http : / /www.springframework.org/schema/c"
xmlns :p="http : / /www.springframework.org/schema/p"
(4)Bean的作用域
singleton(单例模式)默认
"user2" class="com.pojo.user" c:age="18" c:name="花花"scope="singleton" />
@Test
public void test2(){
ApplicationGontext context = new ClassPathXm1ApplicationContext("userbeans.xml" );
User user = context.getBean("user2", User.class);
User user2 = context.getBean("user2", User.class);
System.out.println(user==user2);//true
}
prototype(原型模式) 每次从容器中get的时候,都会产生一个新对象!
"user2" class="com.kuang.pojo.user" c:age="18" c:name=""scope="prototype" />
@Test
public void test2(){
ApplicationGontext context = new ClassPathXm1ApplicationContext("userbeans.xml" );
User user = context.getBean("user2", User.class);
User user2 = context.getBean("user2", User.class);
System.out.println(user==user2);//false
}
3.其余的request、session、application、这些个只能在web开发中使用到!
七、Bean的自动装配
- 自动装配是Spring满足bean依赖一种方式!
- Spring会在上下文中自动寻找,并自动给bean装配属性!
在Spring中有三种装配的方式
- 1.在xml中显示的配置
- 2.在java中显示配置
- 3.隐式的自动装配bean【重要】
1、环境搭建
一个人有猫和狗,猫会叫miao,狗会叫wang
2、测试
bean>
byName自动装配
cat" class="com.pojo.Cat"/>
dog" class="com.pojo.Dog"/>
/// 如果名字是dog222就找不到了
autowire="byName">
bean>
byType自动装配
Cat"/>
Dog">
///Dog">如果多一个Dog类型的就不行了
///Dog">id省略也可以使用
autowire="byType">
小结:
- byname的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法后面的值一致!
- bytype的时候,需要保证所有bean的类型class唯一,并且这个bean需要和自动注入的属性的类型一致!
使用注解实现自动装配
jdk1.5支持的注解,Spring2.5就支持注解了!官方原话:The introduction of annotation-based configurations raised the question of whether this approach is 'better' than XML.
要使用注解须知:
1.导入约束
2.配置注解的支持
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">
@Autowired
- 直接在属性上使用即可!也可以在set方式上使用!
- 使用Autowired我们可以不用编写Set方法了,前提是你这个自动装配的属性在IOC (Spring)容器中存在,且符合名字byname!
@Nullable
@Qualifier
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以使用@Qualifier(value="xxx")去配合@Autowired的使用,指定一个唯一的bean对象注入!
@Resource
会先根据id Name来找,找不到通过Type属性来找
小结:
Resource和@ Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- Autowired通过byType的方式实现,而且必须要求这个对象存在!
- @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现! 如果两个都找不到的情况下,就报错!
- 执行顺序不同:@Autowired 通过byType的方式实现。@Resource默认通过byname的方式实现
八、使用注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入了
使用注解需要导入context约束,增加注解的支持!
- "1.0" encoding="UTF-8"?>
"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">
-
-
-
package="com.pojo"/> -
-
1.bean
@Component
@Component组件 等价于
2.属性如何注入
@Component
public class User {
//@value("huahua")可以放到属性
public String name;
//相当于
@value("huahua") 也可以放到set方法
public void setName(String name) {
this.name = name;
}
}
3.衍生的注解
- @Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!
- dao 【@Repository】
- service 【@Service】
- controller 【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
4.自动装配置
- - @Autowired :自动装配通过类型。名字
- 如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="xxx")
- - @Nullable字段标记了这个注解,说明这个字段可以为null;
- - @Resource:自动装配通过名字。类型。
5.作用域
@Scope
6.小结
xml 与注解:
- xml 更加万能,适用于任何场合!维护简单方便。
- 注解不是自己类使用不了,维护相对复杂!
xml与注解最佳实践:
- xml 用来管理bean;
- 注解只负责完成属性的注入;
- 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
九、使用Java的方式配置Spring
我们现在要完全不使用Spring的xml配置了,全权交给Java来做!
JavaConfig 是Spring的一个子项目,在Spring 4之后,它成为了一个核心功能!
pojo-->User
- //这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中
- @Component
- public class User {
- private String name;
- public String getName() {
- return name;
- }
-
-
- @Value("huahua")//属性注入值
- public void setName(String name) {
- this.name = name;
- }
- @override
- public string toString() {
- return "User{"+
- "name='" +name + '\''+
- '}';
- }
- }
config-->Config 配置文件
- //这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component
- //@Configuration代表这是一个配置类,就和我们之前看的beans.xml
- @Configuration
- @ComponentScan("com.pojo")
- @Import(Config2.class)//两个类引成一个类,相当于导入了
- public class Config {
- //注册一个bean,就相当于我们之前写的一个bean标签
- //这个方法的名字,就相当于bean标签中的id属性
- //这个方法的返回值,就相当于bean标签中的class属性
- @Bean
- public User getUser(){
- return new User();//就是返回要注入到bean的对象!
- }
- }
test--->MyTest
- public class MyTest {
- public static void main(string[] args) {
- //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
- ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
- User getUser = (User) context.getBean("getUser");
- System.out.println(getUser.getName());
- }
- }
这种纯Java的配置方式,在SpringBoot中随处可见!