Spring框架的四大原则:

  1. 使用POJO进行轻量级和最小侵入式的开发。
  2. 通过依赖注入和基于接口编程实现松耦合。
  3. 通过AOP和默认习惯进行声明式编程。
  4. 使用AOP和模板减少模式化代码。

依赖注入

控制反转(Inversion of Control-IOC)和依赖注入(dependency injection-DI)

控制反转是通过依赖注入实现的。所谓的依赖注入指的是容器负责创建对象和维护对象间的依赖关系,而不是通过对象本身负责自己的创建和解决自己的依赖。

Spring IOC容器(ApplicationContext)负责创建Bean,并通过容器将功能类Bean注入到你需要的Bean中。

Spring提供使用XML,注解,Java配置,groovy配置实现Bean的创建和注入。

声明Bean的注解:

@Component 没有明确的角色

@Service 在业务逻辑层(Service层)使用

@Respository 在数据访问层(dao层)使用

@Controller 在展现层使用

注入Beande 的注解,一般情况下通用:

@Autowired Spring提供的注解

@Inject JSR-330提供的注解

@Resource JSR-250提供的注解

关于注解的示例:

引入spring的基础包,当中有对注解的支持。要支持inject需要额外引包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xhf</groupId>
  <artifactId>SpringSample1</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringSample1</name>
  <properties>
  	<java.version>1.7</java.version>
  </properties>
    
  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.1.6.RELEASE</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
      <!-- inject依赖的jar包 -->
      <dependency>
          <groupId>javax.inject</groupId>
          <artifactId>javax.inject</artifactId>
          <version>1</version>
      </dependency>
	</dependencies>  
	 	
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
</project>

定义一个方法,后面通过注入的方式实例化这个方法

package com.xhf.sample1;
import org.springframework.stereotype.Service;

@Service
public class FunctionService {
	public String sayHello(String word) {
		return "Hello " + word + "! ";
	}	
}

这里通过注入实例化Bean,并且进行使用

package com.xhf.sample1;
import javax.annotation.Resource;

import javax.inject.Inject;  
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UseFunctionService {

	//spring提供的注入注解
	@Autowired
	FunctionService functionService1;
	
	//使用这个注解需要引入javax.inject的jar包,maven依赖可已看pom文件
	@Inject
	FunctionService functionService2;
	
	@Resource
	FunctionService functionService3;
	
	public String sayHello(String word) {
		return functionService1.sayHello(word) + functionService2.sayHello(word) + functionService3.sayHello(word);
	}
}

定义一个配置类,确定扫描组件的范围

package com.xhf.sample1;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration  //这表示这是一个配置类
@ComponentScan("com.xhf.sample1") //从这个包里扫描组件
public class DiConfig {

}

执行方法,看看注入是否成功

package com.xhf.sample1;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new 		AnnotationConfigApplicationContext(DiConfig.class);
		UseFunctionService useFunctionService = context.getBean(UseFunctionService.class);
		String result = useFunctionService.sayHello("world");
		System.out.println(result);
		context.close();
	}
	
}


输出:
Hello world! Hello world! Hello world!

AOP

面向切面编程相对于OOP(面向对象编程)能够使代码的耦合度降低。Spring支持AspectJ的注解切面编程。

  1. 使用@Aspect声明是一个切面。
  2. 使用@After @Before @Around 定义建言 advice,可直接将拦截规则(切点)作为参数。
  3. 其中@After @Before @Around 参数的拦截规则为切点(PointCut),为了使切点复用,可使用@PointCut 专门定义拦截规则,然后在@After @Before @Around 的参数中调用。
  4. 其中符合条件的每一个被拦截处为连接点。

这里给出一个简单的示例

添加aspectJ的依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xhf</groupId>
  <artifactId>SpringSample1</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringSample1</name>
  
  <properties>
  	<java.version>1.7</java.version>
  </properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.6.RELEASE</version>
		</dependency>
		
		
		<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
		<dependency>
		    <groupId>javax.inject</groupId>
		    <artifactId>javax.inject</artifactId>
		    <version>1</version>
		</dependency>
				
		<!-- 添加spring aop支持以及AspectJ依赖 -->
		<!-- spring aop支持 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.1.6.RELEASE</version>
		</dependency>
		<!-- aspectJ支持 -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.8.5</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.5</version>
		</dependency>		
	
	</dependencies>  
	 	
	 	<build>
	 		<plugins>
	 			<plugin>
	 				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
	 				<configuration>
	 					<source>${java.version}</source>
	 					<target>${java.version}</target>
	 				</configuration>
	 			</plugin>
	 		</plugins>
	 	</build>
  
</project>

定义一个注解,可以通过注解拦截指定的方法

//此处定义一个注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Action {
	String name();
}

定义几个被拦截的方法

通过注解拦截的方法

@Service
public class DemoAnnotationService {
	
	//在方法上加一个注解,拦截的时候可根据方法上的注解进行拦截
	@Action(name="注解式拦截的add操作")
	public void add() {System.out.println("add 方法执行");};
	
}

正常的方法,后面可根据方法限定名等定义拦截规则进行拦截

@Service
public class DemoMethodService {

	public void add() {System.out.println("add 方法执行");}
	
}

要被around前后都拦截的方法

@Service
public class AroundDemoMethodService {

	public void add() {System.out.println("around add 方法执行");}
	
}

定义切面,这里定义了各种拦截的规则,以及拦截后在切面上执行一些程序

//Aspect声明这是一个切面
@Aspect
//Component让此切面成为spring管理容器的Bean
@Component
public class LogAspectJ {
	
	//通过pointcut可以声明一个切点,参数为拦截规则,下面规则表示所有被Action注解的方法会被拦截
	@Pointcut("@annotation(com.xhf.sample2.Action)")
	public void annotationPointCut(){};
	
	//声明一个一个建言Advice,使用Pointcut定义的切点。在执行完那个被拦截的方法之后会执行这个建言中的程序。
	@After("annotationPointCut()")
	public void after(JoinPoint joinPoint) {
		MethodSignature signature = (MethodSignature)joinPoint.getSignature();
		Method method = signature.getMethod();
		Action action = method.getAnnotation(Action.class);
		System.out.println("注解式拦截 " + action.name());
	}
	
	//这里直接使用execution函数定义拦截规则。
	@Before("execution(* com.xhf.sample2.DemoMethodService.*(..))")
	public void before(JoinPoint joinPoint) {
		MethodSignature signature = (MethodSignature)joinPoint.getSignature();
		Method method = signature.getMethod();
		System.out.println("方法规则式拦截 " + method.getName());
	}
	
	//使用around进行拦截可以在方法执行前后执行一些程序
	@Around("execution(* com.xhf.sample2.AroundDemoMethodService.*(..))")
	public void around(ProceedingJoinPoint joinPoint) {
		System.out.println("around执行前");
		try {
			//被around拦截的方法必须执行这句程序才会执行被拦截的方法
			joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("around执行后");
	}
		
}

定义配置类,开启aspectJ的支持

//表示这是一个配置文件
@Configuration
//spring扫描的包,在这范围内处理各类注解
@ComponentScan("com.xhf.sample2")
//开启spring对aspectJ代理的支持
@EnableAspectJAutoProxy
public class AopConfig {

}

最后是执行一下各个方法,看看拦截的效果

public class Main {
	
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context
			= new AnnotationConfigApplicationContext(AopConfig.class);
		DemoAnnotationService demoAnnotationService
			= context.getBean(DemoAnnotationService.class);
		DemoMethodService demoMethodService
			= context.getBean(DemoMethodService.class);
		
		AroundDemoMethodService aroundDemoMethodService
		= context.getBean(AroundDemoMethodService.class);
	
		
		
		demoAnnotationService.add();
		demoMethodService.add();
		aroundDemoMethodService.add();
		
		context.close();
	}
	
}



输出:
add 方法执行
注解式拦截 注解式拦截的add操作
方法规则式拦截 add
add 方法执行
around执行前
around add 方法执行
around执行后