1、1简介
Spring:春天-->软件行业的春天
2002,首次推出了Spring框架的雏:interface21框架!
Spring框架即以interface21框架为根底,通过从新设计,并不断丰富其外延于2004年3月24日公布了1.0正式版本
Spring Framework创始人,驰名作者。 Rod在悉尼大学不仅取得了计算机学位,同时还取得了音乐学位。更令人吃惊的是在回到软件开发畛域之前,他还取得了音乐学的博士学位
Spring理念:使现有的技术更加的容易应用,自身是一个大杂烩,整合了现有的技术框架!
SSH:Struct2+Spirng+Hibreante
SSM:SpringMVC+Spring+Mybatis
官网:https://spring.io/projects/sp...
官网下载:https://repo.spring.io/releas...
GitHub:https://github.com/spring-pro...
官网外围:https://docs.spring.io/spring...
Maven:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.6.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.6.RELEASE</version></dependency>
1.2长处:
Spring是一个开源的收费的框架(容器)
Spring是一个轻量级、非入侵式的框架
管制反转(IOC)、面向切面编程(AOP)
反对事务的解决,对框架整合的反对
总结一句话:Spring就是一个轻量级的管制反转(IOC),和面向切面编程(AOP)的框架
1、3组成
1、4拓展
Spring官网:现代化的开发就是基于java的开发
Spring Boot
一个疾速开发的脚手架
基于SpringBoot能够疾速开发单个微服务
约定大于配置
Spring Cloud
SpringCloud是基于SpringBoot实现的
因为当初大多数公司都在应用SprigBoot进行疾速开发,学习SpringBoot的前提,须要齐全把握Spring以及
SpringMVC!
弊病:Spring倒退太久,违反了原来的理念!配置非常繁琐,人称“配置天堂”!
2、IOC实践推导
1、UserDao接口
public interface UserDao { void getUser();}
2、UserDaoImpl实现类
public class UserDaoImpl implements UserDao { public void getUser() { System.out.println("默认获取用户的数据"); }}
3、UserService接口
public interface UserService { void getUser();}
4、UserServiceImpl业务实现类
public class UserServiceImpl implements UserService { private UserDao userDao ; //利用Set接口进行动静实现注入 public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void getUser() { userDao.getUser(); }}
在之前的业务中,用户的额需要可能会影响到咱们原来的代码,咱们须要依据用户的需要去批改源代码!如果程序代码量非常大,批改一次的老本代价非常低廉!
咱们应用一个Set接口实现,曾经产生了革命性的扭转!
//利用Set接口进行动静实现注入
public void setUserDao(UserDao userDao) { this.userDao = userDao;}
之前,程序是被动创建对象!控制权在程序员手上!
应用了Set注入后,程序不再具备主动性,而是变成了被动的接管对象
这种思维,从实质上解决了问题,咱们程序员不必再去治理对象的创立了。零碎的耦合性大大降低,能够更加专一于在业务的实现上!这是IOC的原型!
IOC实质
管制反转IoC(Inversion of Control),是一种设计思维,DI(依赖注入)是实现IoC的一种办法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 咱们应用面向对象编程 , 对象的创立与对象间的依赖关系齐全硬编码在程序中,对象的创立由程序本人管制,管制反转后将对象的创立转移给第三方,集体认为所谓管制反转就是:取得依赖对象的形式反转了。
采纳XML形式配置Bean的时候,Bean的定义信息是和实现拆散的,而采纳注解的形式能够把两者合为一体,Bean的定义信息间接以注解的模式定义在实现类中,从而达到了零配置的目标。
管制反转是一种通过形容(XML或注解)并通过第三方去生产或获取特定对象的形式。在Spring中实现管制反转的是IoC容器,其实现办法是依赖注入(Dependency Injection,DI)
3、HelloSpring
1、导人Spring Maven依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.6.RELEASE</version> </dependency> </dependencies>
2、编写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 "Hello{" + "str='" + str + '\'' + '}'; }}
3、编写咱们的Spring文件,命名为beans.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 应用Spring创建对象,在Spring中这些都被称为bean 类型 变量名 = new 类型() Hello hello = new Hello() id = 变量名 class = new 的对象 property 相当于给对象中的属性设置一个值 --> <bean id="hello" class="com.aostarit.pojo.Hello"> <property name="str" value="Spring123"/> </bean></beans>
4、测试
public class MyTest { public static void main(String[] args) { //获取Spring的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //咱们的对象当初都在Spring容器中了,间接通过context去获取就能够获取实例化对象 Hello hello = (Hello) context.getBean("hello"); System.out.println(hello); }}
思考问题?
Hello对象是谁创立的?
Hello对象是由Spring创立的
Hello对象的属性是怎么设置的?
Hello对象的属性是由Spring容器设置的
这个过程就叫管制反转
管制:谁来管制对象的创立,传统应用程序的对象是由程序自身来管制创立的,应用Spring后,对象是由Spring来创立的
反转:程序自身不创建对象,而是变成被动的接管对象
依赖注入:就是利用set办法实现注入的
IOC是一种编程思维,由被动的编程变成被动的接管
能够通过new ClassPathXmlApplicationContext去浏览以下底层源码
OK,到了当初,咱们彻底不再须要程序中去改变了,要实现不同的操作,只须要在xml配置文件中进行批改,所谓的IOC,一句话搞定:对象由Spring来创立、治理、拆卸!
4、IOC创建对象的形式(结构器注入依赖)
1.应用无参结构创建对象,默认
2.应用有参结构创建对象
下标赋值: <!--第一种通过下标赋值注入--> <bean id="user" class="com.aostarit.pojo.User"> <constructor-arg index="0" value="文贤波"/> </bean>类型赋值:<bean id="user" class="com.aostarit.pojo.User"> <constructor-arg type="java.lang.String" value="wxb"/></bean>参数名赋值: <bean id="user" class="com.aostarit.pojo.User"> <constructor-arg name="name" value="123"/> </bean>
总结:在配置文件加载的时候,容器中治理的对象就曾经实现了初始化
5、Spring配置
5.1别名:
应用别名也能够获取对象
<!-- 给对象起别名--><alias name="user" alias="userNew"/>
5.2Bean配置
<!-- id :bean 惟一的标识符,也相当于咱们的对象名 class:bean 所对应的权限命名:包名+类名 name:也是别名 并且name更弱小,能够同时取多个别名 --> <!--第二种通过参数名赋值注入--> <bean id="user" class="com.aostarit.pojo.User"> <constructor-arg name="name" value="user"/> </bean> <bean id="test" class="com.aostarit.pojo.test" name="test2,test3"> <constructor-arg name="id" value="test"/> </bean>
5.2Import
个别用于团队开发应用,它能够将多个配置文件导入合并为一个
假如当初我的项目中由多集体开发,张三,李四,王五,这三个人复制不同的类开发,不同的类须要注册在不同的bean中,咱们能够利用Import将所有人的beans.xml文件合并为一个总的applicationContext.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="beans1.xml"/> <import resource="beans2.xml"/> <import resource="beans3.xml"/></beans>
应用的时候,就间接应用总的配置文件即可
6、依赖注入(DI)
6.1结构器注入
前边曾经说过
6.2Set形式注入
依赖注入:Set注入
依赖:bean对象的创立依赖于容器
注入:bean对象的所有属性,由容器来注入
【环境搭建】
简单类型:
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; }}
实在测试对象:
public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private Properties info; private String wife;}
beans.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.aostarit.pojo.Student"> <!--第一种一般值注入:间接写value属性注入 --> <property name="name" value="wxb"/> </bean></beans>
测试类:
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); }
欠缺注入信息<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="address" class="com.aostarit.pojo.Address"> <property name="address" value="四川成都"/> </bean> <bean id="student" class="com.aostarit.pojo.Student"> <!-- 一般值注入:间接写value属性注入 --> <property name="name" value="wxb"/> <!-- Bean注入 ref --> <property name="address" ref="address"/> <!-- 数组注入 --> <property name="books"> <array> <value>西游记</value> <value>红楼梦</value> <value>三国演义</value> <value>水浒传</value> </array> </property> <!-- list注入 --> <property name="hobbys"> <list> <value>听歌</value> <value>写代码</value> <value>看电影</value> </list> </property> <!-- map注入 --> <property name="card"> <map> <entry key="身份证" value="1234561234561234"/> <entry key="银行卡" value="1111111111111111"/> </map> </property> <!-- set注入 --> <property name="games"> <set> <value>DNF</value> <value>CF</value> <value>LOL</value> </set> </property> <!--null--> <property name="wife"> <null/> </property> <!--propesties --> <property name="info"> <props> <prop key="driver">123456</prop> <prop key="url">男</prop> <prop key="username">小明</prop> <prop key="password">小明</prop> </props> </property> </bean></beans>
6.3拓展形式注入
P命名空间注入:
<!-- p命名空间注入,能够间接注入属性的值--> <bean id="user" class="com.aostarit.pojo.User" p:name="wxb"/>
C命名空间注入:
<!-- c命名空间注入,通过结构器注入,constructor-args --> <bean id="user" class="com.aostarit.pojo.User" c:name="123" c:age="18"/>
测试
@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("user.xml"); User user = context.getBean("user",User.class); System.out.println(user.toString()); }
留神点:应用p命名或者c命名空间注入,须要导入依赖
xmlns:p="http://www.springframework.org/schema/p"xmlns:c="http://www.springframework.org/schema/c"
6.4Bean的作用域
1、单例模式:(Spring默认机制)
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
2、原型模式:每次从容器中get的时候,都会产生一个新对象!
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
3、其余的request、session、application这些只能在web开发中才会用到
7、Bean主动拆卸
主动拆卸是Spring满足Bean依赖的一种形式
Spring会在上下文中主动寻找,并主动给bean拆卸属性
在Spring中有三张主动拆卸形式
在xml中显示配置
在java中显示配置
隐式的主动拆卸bean(重要)
7.1测试
环境搭建:一个人有两个宠物!
7.2ByName主动拆卸
<!-- byName:会主动在容器中查找,和本人对象set办法前面的值对应的beanid --> <bean id="people" class="com.aostarit.pojo.People" autowire="byName"> <property name="name" value="波少"/> </bean>
7.3ByType主动拆卸
<!-- byName:会主动在容器中查找,和本人对象set办法前面的值对应的beanid byType:会主动在容器中查找,和本人对象属性类型雷同的bean --> <bean id="people" class="com.aostarit.pojo.People" autowire="byType"> <property name="name" value="波少"/> </bean>
小结:
byname时,须要保障所有bean的id惟一,并且这个bean须要和主动注入的属性的set办法的值统一
bytyp时,须要保障所有bean的class惟一,并且这个bean须要和主动注入的类的属性统一
7.4应用注解进行主动拆卸
jdk1.5开始反对注解,Spring2.5开始反对注解
要应用注解须知:
导入束缚配置注解的反对:xmlns:context="http://www.springframework.org/schema/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:annotation-config/> <bean id="cat" class="com.aostarit.pojo.Cat"/> <bean id="dog" class="com.aostarit.pojo.Dog"/> <bean id="people" class="com.aostarit.pojo.People"/></beans>
@Autowired
间接在属性上应用即可,也能够在set形式上应用
应用@Autowired咱们能够不必编写set办法了,前提式你这个主动拆卸的属性在IOC(Spring)容器中存在,且合乎名字byname!
科普:
@Nullable 字段标记了这个注解,阐明这个字段能够为NULL
public @interface Autowired { boolean required() default true;}@Autowired(required=false)如果显示的定义了required=false,则示意这个对象能够为null,否则不容许为空public class People { @Autowired(required = false) private Dog dog; @Autowired private Cat cat; private String name;}如果@Autowired主动拆卸无奈通过一个注解实现的时候,咱们能够应用@Qualifier(value = "XXX")去配置@Autowired注解,给其指定一个惟一的Beanpublic class People { @Autowired(required = false) private Dog dog; @Autowired @Qualifier(value = "cat1") private Cat cat; private String name; public Dog getDog() { return dog; } public Cat getCat() { return cat; }}@Resource注解public class People { @Resource private Dog dog; @Resource(name = "cat1") private Cat cat; private String name;}
@Resource和@Autowired的区别:
都是用来进行主动拆卸的,都能够放在属性字段上
@Autowired通过bytype的形式实现,而且必须要求这个对象存在【罕用】
@Resource默认通过byname的形式实现,如果找不到名字,则通过bytype的形式实现!如果两个都找不到,就会报错!【罕用】
执行程序不同:@Autowired通过bytype的形式实现、@Resource默认通过byname的形式实现
8、应用注解开发
在Spring4之后的开发,要应用注解开发,必须要导入aop的包
应用注解须要导入context的束缚,减少注解的反对!
1、bean
2、属性如何注入
//等价于 <bean id="user" class="com.aostarit.pojo.User"/>
@Componentpublic class User { // <property name="name" value="name"/> @Value("value") public String name ; public String getName() { return name; } public void setName(String name) { this.name = name; }}
3、衍生的注解
@Component有几个衍生的注解,在咱们的web开发中,会依照mvc三层架构分层
dao层:【@Repository】
service层:【@Service】
contooller层:【@Controller】
这四个注解性能都是一样的,都是代表将某个类注册到Spring中,拆卸Bean
4、主动拆卸
@Autowired:主动拆卸通过类型—->名字
如果@Autowired不能惟一主动拆卸主属性,则须要通过@Qualifier(value = "XXX")
@Resource:主动拆卸通过名字-->类型
@Nullable 字段标记了这个注解,阐明这个字段能够为NULL
@Component组件:放在类上,阐明这个类被Spring治理了,就是bean!
5、作用域
@Component@Scope("singleton")public class User { // <property name="name" value="name"/> @Value("value") public String name ; public String getName() { return name; } public void setName(String name) { this.name = name; }}
6、小结
xml与注解
xml更加万能,应用于任何场合!保护更加简略
注解不是本人的类应用不了,保护绝对简单
最佳实际:
xml用来治理所有的bean,
注解只负责实现属性的注入
咱们在应用的过程中,只须要留神一个问题,必须让注解失效,就必须开启注解的反对
<!-- 注解扫描的包门路,Spring会扫描该门路下所有的注解--> <context:component-scan base-package="com.aostarit"/>
9、应用Java的形式配置Spring
咱们当初齐全不应用Spring的xml配置了,全权交给java来做
javaConfig是Spring的一个子项目,在Spring4之后,它成为了一个外围性能
实体类
//这个注解阐明这个类被spring治理了,注册到了容器中@Componentpublic class User { private String name; public String getName() { return name; } @Value("wxb")//注入值 public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; }}
配置类
//@Configuration这个类也会被spring治理,注册到容器中,因为Configuration原本就是一个@Component//@Configuration代表这是一个配置类,就和咱们之前的beans.xml一样@Configuration@ComponentScan("com.aostarit.pojo")@Import(UserConfig.class)public class BeanConfig { //注册一个bean:就相当于咱们之前写的一个bean标签 //这个办法的名字,就相当于bean标签的id属性 //这个办法的返回值类型,就相当于bean标签中的class属性 @Bean public User getUser(){ return new User(); }}测试类public class MyTest { public static void main(String[] args) { //如果齐全应用了配置类去做,咱们就只能通过AnnocationConfig上下文来获取容器,通过配置的class对象加载! ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); User user = (User) context.getBean("getUser"); System.out.println(user.getName()); }}
这种纯Java在SpringBoot中随处可见
10、代理模式
为什么要学习代理模式?因为这就是SpringAOP得底层实现原理:【SpringAOP和SpringMVC】
10.1动态代理
角色剖析:
形象角色:个别会应用接口或者是抽象类类解决
实在角色:被代理得角色
代理角色:代理实在角色,代理实在角色后,咱们个别会做一些从属操作
客户:拜访代理得角色得人
代码步骤
接口//租房public interface Rent { public void rent();}实在角色//房东public class Host implements Rent { public void rent() { System.out.println("房东租房"); }}代理角色public class Proxy { private Host host; public Proxy(Host host) { this.host = host; } public Proxy() { } public void rent(){ seeHouse(); host.rent(); hetong(); } public void seeHouse(){ System.out.println("中介代理看房子"); } public void hetong(){ System.out.println("签订合同"); }}客户端拜访代理角色public class Demo01 { public static void main(String[] args) { //房东出租房子 Host host = new Host(); //中介代理模式 Proxy proxy = new Proxy(host); //你不必面对房东,间接找中介即可 proxy.rent(); }}
代理模式得益处
能够是实在角色得操作更加纯正,不必去关注一些公共得业务
公共也就交给代理角色,实现了业务得分工
公共业务发送扩大得时候,不便集中管理
代理模式得毛病:
一个实在得角色就会产生一个代理角色,代码量会翻一倍,开发效率会变低
10.2加深了解
聊聊AOP
10.3动静代理
动静代理和动态代理角色一样
动静代理得代理类是动静生成得,不是咱们间接写好得
动静代理分为两大类:基于接口得动静代理,基于类的动静代理
基于接口:JDK动静代理[咱们在这里应用]
基于类:cglib
java字节码实现:javassist
须要理解得两个类:Proxy代理,InvocationHandler:调用处理程序
动静代理得益处:
能够是实在角色得操作更加纯正,不必去关注一些公共得业务
公共也就交给代理角色,实现了业务得分工
公共业务发送扩大得时候,不便集中管理
一个动静代理类代理得是一个接口,个别就是对应得一类业务
一个动静代理类能够代理多个类,只有是实现同一个接口即可
11、AOP
11.1、什么是AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译形式和运行期间动静代理实现程序性能的对立保护的一种技术。AOP是OOP的连续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP能够对业务逻辑的各个局部进行隔离,从而使得业务逻辑各局部之间的耦合度升高,进步程序的可重用性,同时进步了开发的效率。