目录
1.spring是什么?
我们通常所说的spring指的是springframework(spring框架),它是一个开源框架,有着较活跃和较大的社区,spring支持广泛的应用场景,他可以让java企业级的应用程序开发起来更简单,这也是为什么现在学java必须学习spring系列的原因。
其实总结起来就是一句话:spring就是包含了众多工具方法的Ioc容器
那么我们之前的学习过程中接触过哪些容器吗?
List/Map--->数据存储的容器
Tomcat--->web容器
那么Ioc是什么呢?
一种容器,实现控制反转(获得依赖对象的过程被反转了),应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责创建和维护。
2.理解spring
既然上面我们说了spring是一个Ioc(控制反转)容器,重点还在“容器”二字上,那么它就具备两个最基础的功能
1.将对象存入到容器
2.将对象从容器中取出
也就是说学 Spring 最核心的功能,就是学如何将对象存入到 Spring 中,再从 Spring 中获取对象的过程。
Spring 是一个 IoC 容器,说的是对象的创建和销毁的权利都交给 Spring 来管理了,它本身又具备了存储对象和获取对象的能力。
3.创建spring项目
接下来使用 Maven 方式来创建一个 Spring 项目,创建 Spring 项目和 Servlet 类似,总共分为以下 3 步:
1. 创建一个普通 Maven 项目。
2. 添加 Spring 框架支持(spring-context、spring-beans)。
3. 添加启动类。
创建一个 Maven 项目
添加 Spring 框架支持
在pom.xml文件下导入依赖
导入成功后右侧maven点开后检查plugins和依赖dependencies
如果导入不成功可检查settings.xml文件是否正确
添加启动类
最后在创建好的项目 java 文件夹下创建一个启动类,包含 main 方法即可
4.Bean注入示例
也许你读到这里还是有很多疑惑,说了这么多概念,我还是没搞懂Spring是干嘛的啊!
好吧,让我用学习了两天Spring的经验告诉你,Spring中通过IOC容器来让我们调用对象时无需先创建对象(new一个对象),原来我们写代码的时候,在一个类中调用其他类的方法或变量,如果这个方法或变量不是静态的,那么我们就需要先new出这样一个对象,再通过对象名调用其方法或变量(这样会导致代码结构复杂,耦合度高,难以复用,也难以进行单元测试),现在有了Spring,Spring解放了我们的双手,降低了我们的代码耦合度,我们只需要定义这样一个类型的成员变量,无需new出来,然后通过一些配置方式让这个类型的实例注入到该类中(这实际上是个实例化的过程),这也就是我们所说的依赖注入的概念。
我们来通过一个很简单的例子看看:
我们每个人都拥有一部自己的手机,那么可以创建出一个person类和mobile类来看看:
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Data//这是lombok注解,可以自动生成属性的getter/setter,equals/hashcode,toString
public class Person {
@Autowired
private Mobile mobile;
// public Mobile getMobile() {
// return mobile;
// }
//
// public void setMobile(Mobile mobile) {
// this.mobile = mobile;
// }
}
为了让Spring可以发现并组装我们创建的bean,就要在类上添加@Component注解
@Autowired:自动根据类型注入
相信你对@Data又感到陌生了,看下图:
@Data
: 注解的目标是 类上提供类的get、set、equals、hashCode、canEqual、toString方法
如果方法值默认不写是系统默认值引用这个注解的时候还要加入依赖包才可导入
依赖包如下:
接下来看看mobile类和Main
import org.springframework.stereotype.Component;
@Component
public class Mobile {
}
import org.example.test.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
//Annotation是注解,ApplicationContext是上下文环境(理解为容器)
//new出来是一个注解配置的容器,传入的参数,需要扫描的包路径
//表示的含义:在指定的包路径下,进行扫描,如果是spring框架的注解的类,就会注册到容器中
System.out.println("Hello world!");
ApplicationContext context=new AnnotationConfigApplicationContext("org.example");
Person p= (Person) context.getBean("person");
System.out.println(p);
}
}
需要注意的是:我们“org.example”是扫描包路径,我们需要扫描的包必须在填写的路径下方
我们来执行代码看结果:
可以看到的确比我们以前new对象等等节省了很多行代码
当然我们也可以自定义配置类来使用@Bean方法注解
import org.example.test.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
//定义方法,使用Bean的注解
//如果当前类,可以被容器扫描到,并且会被容器注册中,那就是容器管理的Bean对象
//方法上,使用@Bean,就可以把方法返回值,注册到容器中
//注册的方式:键=方法名,值=返回值
@Bean
public Person p1(){
return new Person();
}
@Bean
public Person p2(){
return new Person();
}
}
我们在此类中定义了两个方法,返回两个person对象,我们接下来编写Main来看看区别:
import org.example.test.Mobile;
import org.example.test.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
//Annotation是注解,ApplicationContext是上下文环境(理解为容器)
//new出来是一个注解配置的容器,传入的参数,需要扫描的包路径
//表示的含义:在指定的包路径下,进行扫描,如果是spring框架的注解的类,就会注册到容器中
System.out.println("Hello world!");
ApplicationContext context=new AnnotationConfigApplicationContext("org.example");
Person p= (Person) context.getBean("person");
System.out.println(p);
Mobile mobile= (Mobile) context.getBean("mobile");
//打印person对象的mobile属性,验证是否是容器中注入的mobile
System.out.println(p.getMobile());
System.out.println(mobile);
System.out.println(p.getMobile()==mobile);
Person p1= (Person) context.getBean("p1");
System.out.println(p1);
System.out.println(p1==p);
Person p2= (Person) context.getBean("p2");
System.out.println(p2);
System.out.println(p1==p2);
}
}
根据结果我们看出为什么p1与p2与p的地址相同,那么为什么它们三个都是返回false呢?
因为我们在person类中使用@Data注解,对于hashcode方法进行了重写
从打印结果来看,我们也可以得出结论,打印相同的是mobile的地址,并不是person本身的地址
5.存储Bean对象
想要将对象存储在 Spring 中,有两种注解类型可以实现:
1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
2. 方法注解:@Bean。
@Controller
:用于标识一个类是Spring MVC
框架中的控制器(Controller)
,处理HTTP请求并返回响应给客户端。@Service
:用于标识一个类是业务逻辑层(Service)
,包含了应用程序中的业务逻辑处理代码。@Repository
:用于标识一个类是数据访问层(DAO,Data Access Object)
,用于访问数据库和其他数据存储介质。@Component
:用于标识一个类是Spring
框架中的组件,一般用于定义那些没有明确角色的类。@Configuration
:用于标识一个类是Spring
的配置类,它可以包含多个bean
的定义。
博主在此处就举一个例子:
使用 @Controller 存储 bean 的代码如下所示:
import org.springframework.stereotype.Controller;
@Controller// 将对象存储到 Spring 中
public class UserController {
public void sayHello(String name){
System.out.println("hello dear "+name);
}
}
此时我们先使用之前读取对象的方式来读取上面的 UserController 对象,如下代码所示:
import org.example.test.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext context=new AnnotationConfigApplicationContext("org.example");
UserController userController= (UserController) context.getBean("userController");
userController.sayHello("jack");
}
}
此时代码运行
我们已经了解了类注解的用法,那这里再来讲一讲关于取Bean对象
的一些知识。上面我们取Bean对象
是用了下面的方式:
还有其它方法,就是用类名加类类型的方式来取Bean对象
:
可以看出,运行结果是完全正确的
那么问题来了,这里的名字"studentService"
是正确的吗?在上面,介绍的是用<bean id="" class="">
的方式来存Bean
对象的,这里的id
就是容器中对象的名称。
我们发现我们类名是UserController ,但是id确实userController,我们对于首字母进行了小写,那么大写不可以吗?我们可以来试试:
报错了,这就说明在取对象的时候,名字要用小驼峰,但事实真是这样的吗?我们再创建一个SController
类:
import org.springframework.stereotype.Controller;
@Controller
public class SController {
public void say(){
System.out.println("SController is very cool");
}
}
再来取对象:
我们看结果:
唉?报错了,我们换回大驼峰试一试:
总结:默认情况下,使用原类名首字母小写(小驼峰)可以读取到 Bean
对象;当原类名首字母与第二个字母为大写的情况下,就用原类名(大驼峰)来读取 Bean
对象。
当然,有一种办法可以指定类的名称:
5
个注解都可以这样指定
好了,今天的文章就到这里了,博主只知道这么多,码字不易,点点赞,感谢。