周六的时候在b站搞了一波模拟面试,三个大学生,属实心态有点崩
因为我看他们都是后端开发,而我是android开发,对Spring不太熟悉,怕出丑,于是周六一天都在恶补spring知识
结果第一个问题 IOC都没人答出来……后面我都不知道怎么问了
最后的视频发出来,又因为同学说隐私啥的不想发出来,没办法,我只能给删了,因为视频很大,如果重新打码,剪辑再导出上传,至少又要两小时起步,我实在是不想在这种事情上浪费时间了
以后模拟面试还是需要设置一下门槛吧
好,今天我们来说说我学习spring的收获,以下所有知识点来自于尚硅谷课程:https://www.bilibili.com/video/BV1Vf4y127N5?from=search&seid=5808667601204981268&spm_id_from=333.337.0.0,
在我的学习笔记基础上,进行润色,讲述给读者
IOC
当我们在java中想要创建一个对象的时候,我们一般是两种方法,new和反射
但是反射一般比较慢,正常的流程都是用new
此时在项目中会出现一个很大的问题,那就是耦合度
比如构造一个Person类,让他去驾驶一个Car,单纯用new的方式,必须要上Person持有Car,显然,理论上来说,Person和Car应该是独立的实体,所以需要IOC,也就是控制反转
自然世界中,创造生命,是神的能力,一旦生命拥有独立创造生命的力量,将会是一场灾难
而在编程世界中,创建对象,也是一个神的能力,如果所有的对象都能无差别创建对像,那这个项目将几乎无法维护
xml
所以spring框架收回了这个能力,你想创建对象,需要在配置文件中进行声明
<bean id = "userDaoImpl" class = "com.littlesong.UserDaoImpl"></bean>
传入id与全限定类名,每一个对象都是一个bean
然后我们在测试类中可以这样写
@Test
public void testBean1() {
ApplicationContext context =
new ClassPathXmlApplicationContext("bean2.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
首先获取上下文context,然后通过context,传入id名称,就获得了UserService这个类
所以,创建对象的能力交给了spring,不论你是哪个类,当你要调用某个类的方法时,只需要通过context即可获取,完全解除了依赖
另外提一下,android开发中,也有一个类似的全局context,在之前进行解耦时也起到了很大的作用
上面说的只是一个简单对象,假如是下面这种稍微复杂的对象呢?
public class Emp {
private String ename;
private String gender;
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
public void add() {
System.out.println(ename+"::"+gender+"::"+dept);
}
}
我们在获取Emp时,还需要同时注入name,gender等信息,同样可以用xml标签进行指定
<bean id="emp" class="com.littlesong.spring5.bean.Emp">
<property name="ename" value="lucy"></property>
<property name="gender" value="女"></property>
<property name="dept">
<bean id="dept" class="com.littlesong.spring5.bean.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>
但是我相信你发现了问题,那就是如果每个类都这样配置,那基本别写代码了,天天写配置文件算了,这也是spring boot出现的原因,不过,除了xml配置之外,我们还有注解的方式
注解
spring内置了四个注解,可以创建Bean对象
@Component
@Service
@Controller
@Repository
比如可以这样写
@Service
public class UserService {
@Value(value = "abc")
private String name;
}
当我们这样定义了UserService的时候,如果有其他类要用到UserService
可以直接
public void testService1() {
ApplicationContext context
= new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
你可能会好奇,xml中我们配置了id,可以通过getBean获取,但是这里我们只有service注解,为什么通过"userService"也可以get到对象呢?这是因为@Service注解默认了其id就是类名首字母小写,如果你想自定义的话,可以这样
@Service(value = "otherService")
当然,我们可以猜想,当我们在执行这行代码
UserService userService = context.getBean("userService", UserService.class);
由于没有配置文件,spring一定在全局扫描扫描注解,所以需要配置一下扫描开关,同时需要有自定义扫描作用域,指定在某些包下扫描,速度更快
<context:component-scan base-package="com.littlesong.spring5.aopanno"></context:component-scan>
除了通过context这种万能工具,我们还可以使用注解@Autowired
@Service
public class UserService {
@Autowired
private UserDao userDao;
}
此时,当我们需要用到userDao时,直接用即可,不需要自己new了
当然,spring的注解很多,各有各的用途,这里不再一一赘述,但是他们都是起到了取代xml文件的功能
AOP
AOP是spring的另外一个思想,中文翻译为面向切面编程
当我们在定义自己的日程表时,我们往往会说:6点要消息,7点要休息;没有人会从0点开始计算自己在哪些事情花了多少时间,然后推出自己的休息时间在几点
实际上这就是一种面向切面的思想
在后端中,会有很多的事件发生,我们需要清楚的知道某个事件A发生之前和发生后的时机,然后往里面可以插入其他方法,就是before与after方法
比如before可以用来做初始化,after可以用来打印日志
同时我们还希望有一些全局的before,或者全局的after,此时需要与具体的事件进行分离,如何让spring明白我们的意思呢?
同样,会用到注解,而这些注解,来自于一个框架,叫做AspectJ
@Component
@Aspect
@Order(3)
public class UserProxy {
}
这里,我们生成一个User的代理类,UserProxy,帮助我们模拟出User类中各种事情的发生
代码如下
public class UserProxy {
@Pointcut(value = "execution(* com.littlesong.spring5.aopanno.User.add(..))")
public void pointdemo() {
}
@Before(value = "pointdemo()")
public void before() {
System.out.println("before.........");
}
@After(value = "execution(* com.littlesong.spring5.aopanno.User.add(..))")
public void after() {
System.out.println("after.........");
}
上面的信息很多,简单说就是我们使用一个ponitcut注解,表示切入点是在User.add方法,
然后再使用Before和After注解,这样我们自定义的before与after方法会自动的在User.add()的前后运行了
因此我们可以很方便的知道任何一个方法运行前后的所有状态,从而掌控整个后端的系统
当然了切面不仅有before与after,那功能就太弱了,我虽然没有用过太多注解,但是理论上,spring应该提供所有有效切面的注解
其他
作为后端,必然要与数据库,打交道,最常见的就是mysql,大型项目可能会用到nosql
后端所有对数据的修改,本质上都是一个一个的事务,所以spring提供了事务管理器,并根据不同的数据源提供了不同的事务管理器
其中,DataSource表示的是使用JDBC,也就是相对比较原始的方式来处理数据库事务,不过现在一般都用过Hibernate或者Mybatis,但是核心不会变,都是在后端与数据库之间进行了一层中间件封装,
另外关于事务的特点不算是spring的内容,本文也不赘述了
最后我们来看看spring的架构图
可以看到他的内容还是很多的,本文并没有完全涉及,不过掌握了IOC与AOP思想,我相信其他内容也会很快掌握,更重要的是,据我所知,几乎没有公司会只用spring了,spring boot,springMVC,dubbo,ZK,RQ等框架层出不穷,可以说学会spring,只是迈向后端的第一步,虽然今年后端很卷
主要是因为算法岗供大于求,很多研究生被迫转后端,
说不定哪天android不行了,我也去卷后端哈哈哈
|