Java Spring框架

Spring是一个基于IOC和AOP结构的J2EE系统的框架。
IOC反转控制是Spring的基础,简单来说就是创建对象由以前的程序员自己new构造方法来调用,变成了交由Spring创建对象。

Spring创建对象
DI依赖注入Dependency Inject。简单地说就是拿到的对象的属性已经被注入好相关值了,直接使用即可。

Spring 框架测试

建立一个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
*
*/
package com.how2java.pojo;

/**
* @author shaoguoliang
*
*/
public class Category {
private int id;
private String name;

public int getId(){
return id;
}

public void setId(int id){
this.id = id;
}

public String getName(){
return name;
}

public void setName(String name){
this.name = name;
}
}

在src文件夹下建立applicationContext.xml文件

在bean中配置类的实例c, 并配置实例属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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">

<bean name="c" class="com.how2java.pojo.Category">
<property name="name" value="category 1" />
</bean>

</beans>

测试Spring类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
*
*/
package com.how2java.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.how2java.pojo.Category;

/**
* @author shaoguoliang
*
*/
public class TestSpring {
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});

Category c = (Category) context.getBean("c");

System.out.println(c.getName());
}
}

运行测试类,获得结果

![testSpring_result](/images/2019-08-11-Java Spring框架/testSpring_result.png)

通过applicationContext注入一个对象

建立一个Product类,其字段中包含Category类。

那么在applicationContext.xml文件中,按如下方式注入对象。注意ref="c"

1
2
3
4
<bean name="p" class="com.how2java.pojo.Product">
<property name="name" value="product 1" />
<property name="Category" ref="c" />
</bean>

通过注解来注入对象

通过context:annotation-config/ 对注入对象行为进行注解

1
2
3
4
5
6
7
8
<context:annotation-config/>
<bean name="c" class="com.how2java.pojo.Category">
<property name="name" value="category 1"/>
</bean>
<bean name='p' class="com.how2java.pojo.Product">
<property name="name" value="product 1"/>
<!-- 在Product代码中加入@Autowired注解 -->
</bean>

Product代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Product {

private int id;
private String name;
@Autowired
private Category category;

public int getId() {
return id;
}
public String getName() {
return name;
}
public Category getCategory() {
return category;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setCategory(Category category) {
this.category = category;
}
}

也可以在setCategory(Category cat) 函数上加@autowired,可以起到同样的效果

除了@autowired之外也可以加上@Resource

1
2
@Resource(name="c")
private Category category;

在applicationContext.xml文件中

添加<context:component-scan base-package="com.how2java.pojo"/>
表示告诉Spring,bean都放在com.how2java.pojo这个包里。注意的是因为配置从applicationContext.xml移植出来了,所以对象初始化要放在类定义里边。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.how2java.pojo;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("p")
public class Product {

private int id;
private String name="product 1";

@Autowired
private Category category;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Category getCategory() {
return category;
}

public void setCategory(Category category) {
this.category = category;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.how2java.pojo;

import org.springframework.stereotype.Component;

@Component("c")
public class Category {

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private int id;
private String name="category 1";
}

AOP面向切面编程

AOP 即 Aspect Oriented Program面向切面编程。
在面向切面编程的思想里边,把功能分为核心业务功能周边功能
核心业务功能,包括登录,增加数据,删除数据等。
周边功能,包括性能统计,日志,事务管理等等。

周边功能在Spring的面向切面编程AOP思想里,即被定义为切面。
在面向切面编程AOP的思想里边,核心业务功能和切面功能分别独立进行开发,然后把切面功能和核心业务功能“编制”在一起,这就叫做AOP。

AOP的基本思路:

  1. 功能分为两大类,辅助功能和核心业务功能
  2. 辅助功能和核心业务功能彼此独立进行开发
  3. 比如登录功能,即使没有性能统计和日志输出也可以正常运行
  4. 如果有需要,就把“日志输出”和“登录”功能编织在一起,这样登录的时候就可以看到日志输出了
  5. 辅助功能,又叫做切面,这种能够 选择性的,低耦合的 把切面和核心业务功能结合在一起的编程思想,就叫做切面编程。
1
2
3
4
5
6
7
8
9
10
11
12
13
//核心功能代码

package com.how2java.service;

/**
* @author shaoguoliang
*
*/
public class ProductService {
public void doSomeService(){
System.out.println("do Some Service");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//切面功能代码1
package com.how2java.aspect;

import org.aspectj.lang.ProceedingJoinPoint;

/**
* @author shaoguoliang
*
*/
public class LoggerAspect {

public Object log(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("start log:" + joinPoint.getSignature().getName());
Object object = joinPoint.proceed();
System.out.println("end log:" + joinPoint.getSignature().getName());
return object;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//切面功能代码2
package com.how2java.aspect;

import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;

/**
* @author shaoguoliang
*
*/
public class PerformerAspect {

public Object spend(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{

long start = System.currentTimeMillis();
System.out.println("start at " + new Date(start));

Object object = proceedingJoinPoint.proceed();

long end = System.currentTimeMillis();
System.out.println("end at"+new Date(end));
System.out.println("total time"+(end-start)+"毫秒");

return object;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//在applicationContext.xml中进行耦合

<beans>
<!-- 声明核心业务 -->
<bean name="s" class="com.how2java.service.ProductService"/>

<!-- 声明日志切面 -->
<bean id="loggerAspect" class="com.how2java.aspect.LoggerAspect"/>
<bean id="performerAspect" class="com.how2java.aspect.PerformerAspect"/>

<aop:config>

<!-- 设置切入点的作用对象和id -->
<aop:pointcut id="loggerCutpoint"
expression=
"execution(* com.how2java.service.ProductService.*(..)) "/>

<!-- 设置切面id -->
<aop:aspect id="logAspect" ref="loggerAspect">
<aop:around pointcut-ref="loggerCutpoint" method="log"/>
</aop:aspect>

<aop:aspect id="performAspect" ref="performerAspect">
<aop:around pointcut-ref="loggerCutpoint" method="spend"/>
</aop:aspect>

</aop:config>
</beans>

运行结果

![AOP](/images/2019-08-11-Java Spring框架/AOP.png)

使用注解方式配置AOP

核心功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.how2java.service;

import org.springframework.stereotype.Component;

/**
* @author shaoguoliang
*
*/
@Component("s")
public class ProductService {
public void doSomeService(){
System.out.println("do Some Service");
}
}

切片功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.how2java.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
* @author shaoguoliang
*
*/
@Aspect
@Component
public class LoggerAspect {
@Around(value = "execution(* com.how2java.service.ProductService.*(..))")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("start log:" + joinPoint.getSignature().getName());
Object object = joinPoint.proceed();
System.out.println("end log:" + joinPoint.getSignature().getName());
return object;
}
}

applicationContext.xml配置文件

1
2
3
<context:component-scan base-package="com.how2java.aspect"/>
<context:component-scan base-package="com.how2java.service"/>
<aop:aspectj-autoproxy/>

其运行结果与上述相类似。