Spring DI & AOP

DI 依赖注入

通常我们分不清IoC与DI有什么区别,在spring中他们是相同概念的,IOC是通过DI实现的。

目的

DI使用组合的思想而非继承,其目的是为了解耦。

实现

spring Ioc容器(ApplicationContext)负责创建Bean,通过容器将Bean注入到你需要的Bean中。可通过xml、注解、java配置实现Bean的创建和注入。

注解配置

声明Bean的注解:
@Component 没有明确角色
@Service 业务逻辑层使用
@Repository 数据访问层使用
@Controller 表示层使用

注入Bean的注解:
@Autowired 最好注解到属性上,可使代码更少

编写功能Bean

package com.demo.di;

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

注入使用Bean

package com.demo.di;

@Service
public class UseFunctionService() {
@Autowired
FunctionService functionService;

public String SayHello(String word) {
return functionService.sayHello(word);
}
}

配置类

@Configuration
@ComponentScan("com.demo.di")
public class DiConfig {}

运行

// Annotation是注释的意思
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(DiConfig.class);

UseFunctionService useFunctionService =
context.getBean(UseFunctionService.class);

useFunctionService.SayHello("di");

context.close();
}

java配置

通过@Configuration 和 @Bean来实现

编写功能Bean

package com.demo.di;

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

使用功能Bean

package com.demo.di;

@Service
public class UseFunctionService() {
FunctionService functionService;

public void setFunctionService(FunctionService functionService) {
this.functionService = functionService;
}

public String SayHello(String word) {
return functionService.sayHello(word);
}
}

配置类

@Configuration
public class JavaConfig {
@Bean
public FunctionService functionService() {
return new FuntionService();
}

@Bean
public UseFunctionService useFunctionService(FunctionService functionService) {
UseFunctionService useFunctionService = new UseFunctionService();
useFunctionService.setFunctionService(functionService);
// 第二种注入方式:
// 如果UseFunctionService未传参functionService
// useFunctionService.setFunctionService(functionService());
return useFunctionService;
}
}

运行

同注解配置

在全局配置中使用java配置(如数据库相关配置),业务Bean的配置用注解配置。

AOP 面向切面编程

目的

为了接耦,让一组类共享相同的行为。

实现

spring支持AspectJ的注解式切面编程
@Aspect 声明是一个切片
@After 拦截后前执行
@Before 拦截之前执行
@Around 同时在拦截前后执行

添加spring aop支持及AspectJ依赖

<!--aop支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</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>

注解式拦截

拦截规则的注解

package com.demo.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@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("注解拦截服务运行中。。。");
}
}

编写切面

@Aspect
@Component
public class LogAspect {
// 声明切点
@Pointcut("@annotation(com.demo.aop.Action)")
public void annotationPointCut() {
}

@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());
}
}

配置类

@Configuration
@ComponentScan("com.demo.aop")
// 开启Spring 对 AspectJ代理支持
@EnableAspectJAutoProxy
public class AopConfig {
}

运行

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AopConfig.class);

DemoAnnotationService demoAnnotationService =
context.getBean(DemoAnnotationService.class);

demoAnnotationService.add();

context.close();
}

方法式拦截

被拦截类

@Service
public class DemoMethodService {
public void add(){
System.out.println("方法拦截服务运行中");
}
}

编写切面

@Aspect
@Component
public class LogAspect {
@Before("execution(* com.demo.aop.DemoMethodService.*(..))")
public void before(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println("方法规则式拦截," + method.getName());
}
}

配置类

同注解式拦截

运行

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AopConfig.class);

DemoMethodService demoMethodService =
context.getBean(DemoMethodService.class);

demoMethodService.add();

context.close();
}

在springboot项目中@EnableAutoConfiguration默认开启@EnableAspectJAutoProxy。