1.3 Spring基础: Spring基础配置
1.Spring框架的四大原则
1.使用pojo进行轻量级和最小侵入式开发
2.通过依赖注入和基于接口编程实现松耦合
3.通过AOP和默认习惯进行声明式编程
4.s使用AOP和 模板(template)减少模式化代码
1.3.1 依赖注入
1.IOC(Inversion of Controller 控制反转)和DI(dependency injection依赖注入)在Spring下是等同的概念。控制反转是通过依赖注入实现的
2.依赖注入:容器负责创建和维护对象之间的依赖关系(而不是对象子创建和维护)
3.依赖注入目的:解耦,体现了一种组合的理念。组合使耦合度大大降低
4.Bean的创建和注入4种方式:
4.1 XML
4.2 注解
4.3 Java配置
4.4 groovy配置
5.配置元数据:
5.1 定义:描述数据的元素(xml配置,注解配置,java配置都称为元数据)
5.2 元素据本身不具备任何可执行的能力,只能通过外界代码解析后才有意义
5.3 spring解析这些元数据进行Bean的初始化,配置和管理依赖
注解:
1.声明式注解
@Component组件 -> 没有明确的角色
@Service -> 业务逻辑层(Service层)使用
@Repository -> 数据访问层(dao层)使用
@Controller -> 表现层(MVC->SpringMVC)使用
2.注入式注解(一般情况下通用) (可以放在set和属性上,属性上更简洁)
@Autowired : Spring 提供的注解
@Inject : JSR-330提供的注解
@Resource : JSR-250提供的注解
1.3.2 java配置
概念
1.java配置 是Spring4.x推荐的配置方式,可以完全替代XML
2.java配置 也是SpringBoot的推荐配置方式
3.java配置 通过@Configuration和@Bean来实现
3.1 @Configuration声明当前类是一个配置类,相当于之前Spring的XML
3.2 @Bean 注解在方法上,声明当前方法返回一个Bean
使用java配置和注解配置的场景:
1.全局配置使用Java配置(如数据库相关,Redis,MQ相关)
2.业务Bean配置使用注解
1.3.3 AOP
1. AOP 是面向切面编程,相对于面向对象编程OOP
2. AOP的存在是为了解耦,AOP可以让一组类共享相同的行为,弥补了OOP的不足
3. Spring支持AspectJ注解式切面编程
3.1 使用@Aspect申明是一个切面
3.2 使用@After,@Before,@Around定义建言,可以将切点作为参数
3.3 使用切点@PointCut专门定义拦截规则,作为@After,@Before,@Around参数(提高复用)
3.4 符合条件的每一个被拦截处为连接点JoinPoint
举例
(记住,需要配置开启切面支持EnableAspectJAutoProxy)
package com.demo.inspect.config.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.UUID;
@Aspect
@Component
public class LogAop {
protected final Logger logger = LoggerFactory.getLogger(getClass());
@Pointcut("execution(* com.demo.inspect.*.controller.*.* (..))")
private void pointcut() {
}
/**
* ProceedingJoinPoint 继承的 JoinPoint 比JoinPoint , 只多了执行的proceed Around </>一旦执行了这个方法,如果不调用proceed
* , 就会导致调用终止 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice
*/
@Around(value = "pointcut()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info("[拦截]执行方法 - > {} 参数 -> {}{}", joinPoint.getSignature(), joinPoint.getArgs());
try {
Object result = joinPoint.proceed(); //继续下一个方法的调用 :就是调用拦截的函数,得到拦截函数执行的结果
return result;
} catch (BussinessException e) {
throw e;
} catch (Exception e) {
UUID uuid = UUID.randomUUID();
ErrorResponse response = new ErrorResponse();
response.setRequestId(uuid.toString());
response.setSignature(joinPoint.getSignature().toLongString());
response.setArgs(joinPoint.getArgs());
response.setErrorMessage(e.getMessage());
response.setEx(e);
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
String detail = stringWriter.toString();
response.setDetail(detail);
logger.error("[拦截]:{}", response);
return new ModelAndView("errorAop", "response", response);
}
}
}
package com.demo.inspect.config.aop;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(value = "com.demo.*")
public class AopConfig {
}