一. Spring 框架介绍。
Spring 框架是 一个基于 IoC 和 AOP 的 J2EE 框架。
IoC(控制反转,也叫作依赖注入) 是实现 Spring 的基础。IoC的作用是将控制权交给调用方,由调用方决定到底应该创建那个具体的实例。
IoC 在 Spring 框架中的作用是将以前程序员手动自己通过 new 创建对象交由 Spring 容器来进行。
AOP (面向切面编程) 即将需要实现的功能分为核心功能和周边功能,在 Spring AOP编程思想中,就将周边事物确定为切面。
核心功能和周边功能可以分开开发,最后整合编织在一起运行,就是 AOP。
二. Spring框架的依赖
首先需要 Spring 框架的 jar 包。
这里使用How2j 网站提供的整理好的 jar 包。点击下载
另外,推广一下这个网站,还是挺好用的。 How2j
三. Spring框架初探
Spring Ioc 部分
要想使用 Spring,首先我们需要对其进行配置。
在项目的根目录创建 applicationContext.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
</beans>
创建我们需要的实体类Category,它有两个属性分别为 int 类型的 id 与 String 类型的 name,并分别实现他们的 getter 与 setter 方法。
// Category.java
public class Category {
private int id;
private String name;
//getter,setter方法
}
然后修改我们的 appalicationContext.xml 文件。在 beans 标签内添加我们对应实体类的 bean 标签。添加方法如下:
<!-- applicationContext.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans //...省略重复部分>
<bean name="category" class="com.tadecather.spring.pojo.Category">
<property name="name" value="category 1" />
<property name="id" value="12" />
</bean>
</beans>
其中 bean 标签内的 name 属性是 Spring 寻找实体类时所使用的名称,相当于时别名; class 属性 为对应实体类的完整名称,也就是 包名+类名。
bean 标签内的 <property> 标签内的 name 为对应的实体类的属性,value 标签为属性具体值。
可以每一个标签都配置属性,也可以选择一部分甚至全部都不设置属性,那么将采用对应类型的默认值为其赋值。
接下来编写我们的测试代码:
//TestSpring.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tadecather.spring.pojo.Category;
import com.tadecather.spring.pojo.Product;
public class TestSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"});
Category c = (Category)context.getBean("category");
System.out.println(c.getName() + ":" + c.getId());
Product p = (Product) context.getBean("product");
System.out.println(p.getId() + "name: " + p.getName());
}
}
执行结果如下图所示:
如果 Product类中有一个 Category 类,那么我们应该要如何实现呐?
在 Product 类中添加属性Category category。 Category category;
并实现它的 getter,setter 方法。
修改 appalicationContext.xml 添加 另外一个 bean 标签。如下:
<!--
<bean name="product" class="com.tadecather.spring.pojo.Product">
<property name="id" value="13" />
<property name="name" value="apple" />
<property name="price" value="12.33" />
<property name="category" ref="category" />
</bean>
使用 ref 属性指向我们已经定义好的 category 的标签上。
修改TestSpring.java 的最后输出语句为 System.out.println(p.getCategory().getName());
得到如下结果:
通过在上面的代码中使用 ref 属性,我们实现了注入对象的功能。
接下来,我们通过注解的方式实现对象注入:
- 在 applicationContext.xml 中添加这样一行:
<context:annotation-config/>
,同时删除上面 ref 的那一行。 - 在Product.java 的 category 属性前加上 @Autowired 注解。
- 然后运行我们的 TestSpring.java 得到如下结果:
(是的,结果一样,原谅我用了一张图!) - 在 setCategory() 前面添加 @AutoWired 达到同样的功能。
- 注解 @Resource(name="category") 也可以达到同样效果。
最后,我们来实现对 Bean 的注解。
删除 appalication 中的<bean> 子标签,以及刚刚添加的 <context:annotation-config/>
,
然后添加一行 <context:component-scan base-package="com.tadecather.spring.pojo"/>
,告知我们的 Bean 组件在 这个包中。
最后,在Category 以及 Product 类的前面添加注释 @Component
运行我们的测试程序,结果如下:
Spring AOP 部分
使用标签实现
首先创建需要用到的核心业务类,里面只有一个方法 doSomeService(),用来简单的输出一句话。
// ProductService.java
public class ProductService {
public void doSomeService(){
System.out.println("do someService!");
}
}
接下来,实现 Aspect 类,LoggerAspect 类,里面有一个 log() 方法,接受一个 ProceedingJoinPoint 参数,返回一个 Object 对象。
// LoggeAspect.java
import org.aspectj.lang.ProceedingJoinPoint;
public class LoggerAspect {
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("start proceeding!" + joinPoint.getSignature().getName());
Object object = joinPoint.proceed();
System.out.println("end proceeding!" + joinPoint.getSignature().getName());
return object;
}
}
ProceedingJoinPoint 对象的 proceed() 会抛出一个 ThrowAble 。
最后修改 applicationContext.xml 如下:
<!-- applicationContext.xml 部分
<?xml version="1.0" encoding="UTF-8"?>
...
<bean name="s" class="com.tadecather.spring.service.ProductService" />
<bean id="loggerAspect" class="com.tadecather.spring.aspect.LoggerAspect"/>
<aop:config>
<aop:pointcut id="loggerCutpoint"
expression=
"execution(* com.tadecather.spring.service.ProductService.*(..)) "
<aop:aspect id="logAspect" ref="loggerAspect">
<aop:around pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>
</aop:config>
</beans>
在 xml 文件中,我们首先添加了 ProductService 与 LoggerAspect 的 Bean 标签。
然后,添加 <aop:config> 标签,在标签内对 AOP 进行配置。
需要配置的标签有两个,第一个为 <aop:pointcut> 这个标签指定程序在运行到哪一步时会触发下面一个标签 <aop:aspect> 的内容。
其中,expression 属性指明触发的条件 ,本例子中的触发条件为,当执行到 ProductService 类中的任何一个方法时,执行下面的切面函数。 第一个*指的是任意返回值,第二个*是任意函数函数,括号内的 .. 表示任意参数。
执行的步骤大致就是,执行到标记的函数的时候,会将程序的控制权交给切面函数,然后会在切面函数中执行需要执行的函数,当然,可以在执行之前添加一些别的操作,例如打印日志。
执行程序,效果如下:
使用注释实现
使用注释注入对象的方法修改 ProductService 类和 LoggerAspect 类。
然后在LoggeerAspect 类中加入实现 AOP的注释,修改后的 LoggerAspect 如下:
// LoggerAspect.java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component("loggerAspect")
public class LoggerAspect {
@Around(value = "execution(* com.tadecather.spring.service.ProductService.*(..))")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("start proceeding!" + joinPoint.getSignature().getName());
Object object = joinPoint.proceed();
System.out.println("end proceeding!" + joinPoint.getSignature().getName());
return object;
}
}
@Aspect 直接表明这是一个切面
@Component("loggerAspect") 注解,表明这是一个别名为 loggerAspect 的 Bean 组件
@Around(value = "execution(* com.how2java.service.ProductService.*(..))") 表明在使用
com.tadecather.spring.service 的任意方法时,会触发这个切面处理函数。
并在 applicationContext.xml 文件中加入扫描路径,与自动处理 AOP 的语句。
<!-- applicationContext.xml 部分 -->
<context:component-scan base-package="com.tadecather.spring.service"/>
<context:component-scan base-package="com.tadecather.spring.aspect"/>
<aop:aspectj-autoproxy/>
执行 TestSpring.java 效果如下:
注解方式测试
要求:需要使用到测试依赖 jar 文件:junit-4.12.jar 和 hamcrest-all-1.3.jar ,下载并导入项目。
junit-4.12.jar
hamcrest-all-1.3.jar
操作:
- @RunWith(SpringJUnit4ClassRunner.class) 标注这是一个测试类
- @ContextConfiguration("classpath:applicationContext.xml") 配置文件位置
- @Test 测试方法
- 将 TestSpring 修改为下面形式
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestSpring {
@Autowired
Category c;
@Test
public void test(){
System.out.println(c.getName());
}
}
- 测试结果如下:
到此,Spring 框架的初步学习,到此结束。
以上内容 来自这里!
然后加上了一点我的学习思考。
2017.09.23 tadecather