Spring 初探

Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,如今已经发展成为事实上的业界标准,它有两个核心的理念:IoC 和 AOP,我想写几篇文章来分析一下这两个理念以及它们在 Spring 中的具体实现细节,这篇文章先用一段简单的程序来体验一下。

下面程序的 main() 方法中,首先根据配置文件 web-context.xml 创建了一个 IoC 容器,然后从容器中取出一个叫做 testController 的 bean,并调用这个 bean 的 sayHello() 方法,最后得到了两行输出。

public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("web-context.xml");
TestController controller = (TestController) context.getBean("testController");
controller.sayHello();
}
}

// TestAspect.doBefore()
// TestServiceImpl.sayHello()

配置

来看配置文件 web-context.xml,其中只有两行配置:打开 AOP 自动代理和注解扫描,现在使用纯 Java 代码也能实现与配置文件等价的功能,总之 Spring 会根据这份配置创建 IoC 容器并开启相关的功能。

<?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:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.wind4869"/>

</beans>

IoC

IoC 全称 Inversion of Control(控制反转),Spring 官方文档说「IoC is also known as dependency injection (DI)」,即在 Spring 中 IoC 又称为 DI(依赖注入)。看下面的 TestController 类,依赖于一个实现 TestService 接口的类,通常情况下我们需要在最开始的代码中创建出一个 TestServiceImpl 对象,然后在创建 TestController 对象的时候传入。但在最开始的那段代码中,我们并没有手动创建 TestServiceImpl 对象,这部分工作是 Spring 容器帮我们做的,Spring 容器在创建 TestController 对象时会先将它依赖的对象创建出来,然后「注入」进来。

我们不再需要主动去创建依赖的对象,只要在程序中定义好依赖,IoC 容器会帮我们创建并注入到需要的地方,这个「反转」就反转在让你从原来的事必躬亲,转变为现在的享受服务。

@Component
public class TestController {
private final TestService testService;

public TestController(TestService testService) {
this.testService = testService;
}

@TestAnnotation
public void sayHello() {
testService.sayHello();
}
}

public interface TestService {
void sayHello();
}

@Component
public class TestServiceImpl implements TestService {
@Override
public void sayHello() {
System.out.println("TestServiceImpl.sayHello()");
}
}

AOP

AOP 全称 Aspect-Oriented Programming(面向切面编程),它可以通过一个模块化的统一实现,在多处业务代码中插入记录日志或权限校验等系统性的功能,就像在系统中找到一些「截面」,把某个功能「插入」进去。TestAspect 类中的 @Before("@annotation(TestAnnotation)") 注解就定义了应该在什么地方插入什么样的事情:在执行 TestAnnotation 修饰的方法之前先执行 doBefore() 方法,所以我们在程序的运行结果中可以看到对应的输出。这样,如果想在其他方法执行之前做 doBefore() 做的操作,只要在这个方法上面加上 @TestAnnotation 注解就可以了。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}

@Aspect
@Component
public class TestAspect {
@Before("@annotation(TestAnnotation)")
public void doBefore() {
System.out.println("TestAspect.doBefore()");
}
}
0%