2021年第一篇原创——Spring核心初探~

334 阅读4分钟

写在前面

说起Spring,可以说让我没少碰壁,只怪自己太水。谈起Spring,难免会想到IoC和AOP,其实这些还不够,还有Bean、事务等。今天就一起聊聊我对Spring的理解。

Spring IoC

控制反转官方定义是一种通过描述(XML或注解)并通过第三方生产或获取特定对象的方式,在Spring中实现控制反转的是IoC容器。既然IoC容器能为我们创建对象,前提是我们得给他说创建什么对象吧,所以我们一般都是通过XML配置class属性为包名加类名,IoC容器通过反射来创建对象。
<bean id="people" class="com.hzy.pojo.People"/>
另一种方式可以通过给类加注解,例如@Component和他的衍生注解(@Controller、@Service、@Repository),这样IoC容器就知道创建哪个对象了。

@Component
public class People {
}

创建了对象,然后可以对其属性值进行注入,其中注入是通过DI依赖注入来实现的,注入方式有setting、构造器和注解
setting注入

<bean id="student" class="com.zhiying.pojo.Student">
    <property name="name" value="张三"/>
</bean>

也可以通过p命名空间

<bean id="student" class="com.hzy.pojo.Student" p:name="张三"/>

构造器注入

<bean id="teacher" class="com.hzy.pojo.Teacher">
    <constructor-arg name="name" value="张三"/>
</bean>

也可以通过c命名空间

<bean id="teacher" class="com.hzy.pojo.Teacher" c:name="张三"/>

构造器注入

@Component
public class Student {
    @Value("张三")
    private String name;
    @Value("18")
    private int age;
}

Spring AOP

AOP是面向切面的意思,他的最细粒度是对方法的,也就是他可以在方法执行前后横向切入一些通知,开发中一般通过注解的方式来实现。
AOP的底层实现是通过动态代理实现的,有两种方式,一是JDK的动态代理,只提供接口的实现,即代理类要实现InvocationHandler接口,如果代理类没有实现该接口,那么就会通过CGLIB动态代理目标类。

@Aspect //标注这是一个切面
public class AnnotationPointCut {
    @Before("execution(* com.zhiying.service.UserServiceImpl.*(..))")// 这是切入点
    public void beforeLog() {// 该方法是通知
        System.out.println("---方法执行前---");
    }

    @After("execution(* com.zhiying.service.UserServiceImpl.*(..))")
    public void afterLob() {
        System.out.println("---方法执行后---");
    }

Spring Bean

那Bean又是怎么回事呢,其实很好理解,就是我们平时定义的实体类,里面的属性用private关键字修饰,有get和set方法,被Spring容器所管理的对象,那他就是一个Bean,显然一个项目中会有很多的Bean。

例如有一个Computer类

public class Computer {
    private String cpu;

    public Computer(String cpu) {
        this.cpu = cpu;
    }
}

然后有一个Person类

public class Person {
    private Computer computer;

    public Person(Computer computer) {
        this.computer = computer;
    }
}

这种写法就是比较合适的写法,即通过构造器注入,这种注入方式,在项目初始化的时候,会先加载Computer类,因为他是Person类的前置条件。

@Data
public class Person {
    private Computer computer;
}

或者是这种写法,运行时通过set动态注入。

Bean的作用域,常用的有singleton单例,prototype原型,也就是多例。
<bean id="teacher" class="com.hzy.pojo.Teacher" scope="singleton"/>
<bean id="teacher" class="com.hzy.pojo.Teacher" scope="prototype"/>
如果有线程安全问题,用prototype
另外就是关于Bean的生命周期,一共可以分为七步。

1、构造器构造实例
2、注入值
3、初始化之前执行后置处理器的before方法,即实现BeanPostProcesser
4、初始化init-method
5、初始化之后执行后置处理器的after方法,即实现BeanPostProcesser
6、可以使用
7、销毁destory-method

自动装配

自动装配也即是把一个类交给spring来管理,我们声明一下即可使用,自动装配常用的有byType和byName。
<bean id="teacher" class="com.hzy.pojo.Teacher" autowire="byType"/>
<bean id="teacher" class="com.hzy.pojo.Teacher" autowire="byName"/>
一般我们都是使用注解来开发。

@Autowired 默认是byType,可以通过@Qualifile为byName。
@Resource 默认是byName,找不到自动byType。

Spring事务

Spring中的事务,用注解实现也就是一个@Transactional,这个注解有六个参数

1、propagation传播行为,也就是多事物之间进行调用的时候做出的一些策略,例如a方法调用b方法。有两个常用的参数,REQUIRES如果a方法有事务,b方法没事务,那么b会跟着a事务进行运行,如果a没有事务,b有事务,那么会创建新的事务,REQUIRES_NEW不管ab方法是否有事务,都会创建新事务。
2、isolation隔离级别,也就是数据库的四种隔离级别。
3、timeout超时时间,开启事务到提交的时间,默认是-1无限,可以自定义单位是秒。
4、readOnly是否只读,默认是false,若为true,则不能增删改
5、rollbackFor哪些异常回滚
6、noRollbackFor哪些异常不回滚\