spring
基础
-
核心容器:BeanFactory、ApplicationContext(继承BeanFactory)
-
依赖注入/控制反转:对象的实例不再由调用者创建,统一交给spring管理。
-
bean的作用域:singleton、prototype(多例).
-
bean实例化:
构造器实例化(最常用);
静态工厂:factory-method;
实例工厂:factory-method、fatory-bean;
-
spring可以管理singleton类型的bean的完全生命周期,对于prototype类型只负责创建,后续bean的实例交给客户端代码管理。
-
如果BeanPostProcessor和bean关联,则bean在初始化中会调用PostProcessBeforeInitialzation()和PostProcessAfterInitialzation()方法;这个是spring的AOP实现原理。
-
如果bean实现了InitializingBean接口,则spring初始化时将调用afterPropertiesSet()方法。
-
如果bean实现了DisposableBean接口,则bean在被销毁时spring会调用destory()方法。
-
bean的装配方式:
基于xml:设值注入、构造方法注入。
基于注解: @Component、@Controller、@Service、@Repository @Autowired 默认按照类型注入,配合@Qualifer可以通过名称注入。
@Resource 可以配置name、type属性,按照名称或类型注入。 使用注解需要配置包扫描。自动装配:byName、byType;默认通过名字注入。
-
bean的生命周期、启动流程
1、首先是实例化、属性赋值、初始化、销毁这 4 个大阶段;
2、再是初始化的具体操作,有 Aware 接口的依赖注入、BeanPostProcessor 在初始化前后的处理以及 InitializingBean 和 init-method 的初始化操作;
执行BeanPostProcesser前置处理 -->
执行实现了InitializingBena接口的afterPropertiesSet方法 -->
执行BeanPostProcesser后置处理;
3、销毁的具体操作,有注册相关销毁回调接口,最后通过DisposableBean 和 destory-method 进行销毁。
AOP
-
AOP:面向切面编程,传统的OOP只能实现父子关系的纵向复用,aop是通过横向抽取的机制实现的。
-
目前AOP框架主要有spring AOP和 AspectJ。
- spring的aop是在运行时通过动态代理的方式,织入横向代码;
- AspectJ是提供的单独的编译器,在预编译期间织入横向代码。
-
spring AOP的动态代理:
- 基于JDk的动态代理;
- 基于CGLIB的动态代理。
spring会优先使用jdk动态代理,如果代理对象没有实现接口,则使用cglib动态代理。
-
springBoot2.0之前,不配置默认优先jdk动态代理; 从springBoot2.0(含)之后开始,如果用户默认没有配置,则默认优先使用cglib作为动态代理; 可以使用spring.aop.proxy-target-class参数控制动态代理的默认选项;
-
@Transactional注解也是通过spring的aop的实现的,通过捕获异常来控制事务的commit或rollback。
-
Spring中通过ProxyFactoryBean是创建AOP代理的最基本方式。
-
关于动态代理的demo
// 代理工厂
public class JdkDynamicProxyFactory<T> implements InvocationHandler {
private T target;
public JdkDynamicProxyFactory(T target) {
this.target = target;
}
public <T> T getInstance(){
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
myLog();
return method.invoke(target, args);
}
public void myLog(){
System.out.println("打印log....");
}
}
// 调用
public static void main(String[] args) {
StudySpring study = new StudySpring();
// JdkDynamicProxyFactory factory = new JdkDynamicProxyFactory(study);
// Improve improve = (Improve) Proxy.newProxyInstance(study.getClass().getClassLoader(), study.getClass().getInterfaces(), factory);
// improve.study("springBoot");
JdkDynamicProxyFactory factory = new JdkDynamicProxyFactory(study);
Improve improve = (Improve) factory.getInstance();
improve.study("springBoot2.0");
}
- 切入点表达式:
返回值 包名.类名.方法名(..参数类型,两个点表示任意参数)
- aop执行顺序:
正常场景:前置通知、环绕开始、执行业务逻辑、最终通知、环绕结束、后置通知;
异常场景:前置通知、环绕开始、最终通知、异常通知。
- 使用AspectJ实现aop主要有:基于xml声明,基于注解声明。
xml相关配置:
<aop:config> xml配置现在基本不用了,暂不详述
基于注解:
@Aspect 定义一个切面;
@Pointcut 定义切入点表达式;对应的方法签名就是返回void,方法体为空的普通方法;
@Before 前置通知;
@AfterReturning 后置通知;
@Around 环绕通知;
@AfterThrowing 异常通知;
@After 最终通知,不管是否发生异常都会执行;
下面是个简单的demo
@Aspect // 声明切面
@Component
public class ParamAspect {
// 定义切点
@Pointcut("execution(public * com.pancm.web.*.*(..))")
public void doOperation() {
}
@Before("doOperation()")
public void before(JoinPoint joinPoint) throws Throwable{
Object[] objs = joinPoint.getArgs();
System.out.println("前置通知接受的参数:"+(User) obj);
}
@AfterReturning(pointcut = "doOperation()")
public void doAfterReturning(JoinPoint joinPoint) {
System.out.println("后置通知!");
}
- 和注解配合使用aop
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target(ElementType.METHOD)//作用于方法
public @interface MyAnnotation {
String methodName () default "";
}
//切面类中定义增强,pointcut连接点使用@annotation(xxx)进行定义
@Around(value = "@annotation(around)") //around 与 下面参数名around对应
public void processAuthority(ProceedingJoinPoint point,MyAnnotation around) throws Throwable{
System.out.println("ANNOTATION welcome");
System.out.println("ANNOTATION 调用方法:"+ around.methodName());
System.out.println("ANNOTATION 调用类:" + point.getSignature().getDeclaringTypeName());
System.out.println("ANNOTATION 调用类名" + point.getSignature().getDeclaringType().getSimpleName());
point.proceed(); //调用目标方法
System.out.println("ANNOTATION login success");
}
@EnableAspectJAutoProxy(proxyTargetClass=true)是Spring AOP开启的标志,proxyTargetClass来指定Spring AOP使用哪种动态代理方式来创建代理类(默认使用基于实现接口的JDK动态代理方式)。
数据库开发与事务
-
spring提供了JdbcTemplate这个bean,简化了与数据库的交互;
-
JdbcTemplate需要进行数据库的初始化配置,提供了execute()、query()、update()等方法。
-
spring中事务管理涉及3个核心接口: PlatformTransactionManager、TransactionDefinition、TransactionStatus
-
spring中事务管理分为编程式事务、声明式事务;
- 编程式事务:通过编写代码实现的事务管理,包括定义事务的开始、事务的commit、异常时的rollback。
- 声明式事务:通过AOP实现,推荐。
-
声明式事务分为通过xml配置、通过注解配置。
// xml配置
<tx:advice>
// 注解方式
@Transactional
可以作用于类或方法上(不过对private方法不生效,因为无论是jdk动态代理还是cglib子类继承父类都无法对private方法进行调用)。
- 事务的传播行为、隔离级别 可以展开了解下,目前在实践中用的比较少。
Mybatis
-
ORM框架,支持存储过程、动态sql。
-
核心对象是SqlSessionFactory(用于生成SqlSession)、SqlSession(提供了丰富的增删改查方法、commit、rollback方法)。
-
动态sql提供的标签
<if test=""></if>
<choose> <when test=""> <otherwise>
<where> 配合<if>使用;
<trim> 用于动态去除where条件后的and;
<set> 用于update语句;
<foreach> 用于遍历数组或集合;
<bind> 通过OGNL表达式创建一个上下文变量。
- Mapper接口的名称和对应的Mapper.xml文件的名称必须一致。
springMVC
-
@Controller
-
@RequestMapping(value="", method="")
-
@RequestParam(value="user_id" Integer id) 前端参数映射
-
json格式包括两种:
- {"key1":"value1","key2":"value2"....}
- ["abc",123,false]
-
@RequestBody 用于入参的json格式化;该注解用在方法的形参上。
-
@ResponseBody 用于出参的json格式转化;该注解用在方法上。
-
RESTful风格请求,将put、delete、post、get方式分别对应添加、删除、修改、查询操作。服务端可以使用@PathVariable() 来获取url上的参数。
-
springMVC中的拦截器
实现方式有两种,实现HandlerInterceptor接口或WebRequestInterceptor接口;并且在xml中配置。
例如实现HandlerInterceptor接口,重写preHandle、postHandle、afterCompletion方法。
- 文件上传: 前端表单需要指定multiple,后端入参中通过MultipartFile接收文件,MultipartFile提供了getInputStream、getSize、isEmpty等方法。使用List<MultipartFile 接收多文件上传。
一些注解
- @PostConstruct注解作用是容器初始化完成后自动执行此方法,定义的是初始化方法。或者在xml配置中通过 init-method="bean中的方法名"来指定。
// 获取某个接口的所有实现类,并且找出其中用自定义注解标注的实现
Map<String, Animal> animalMap = applicationContext.getBeansOfType(Animal.class);
animalMap.values().stream().foreach(animal -> {
MyAnnotation myAnnotation = animal.getClass().getAnnotation(MyAnnotation.class);
if (myAnnotation != null){
// do something
}
});
执行顺序:
- 实例化:调用bean的无参构造方法;
- 属性赋值:调用set方法赋值属性;
- BeanPostProcessor的前置处理;
- InitializingBean方法执行;
- 初始化:调用bean的初始化方法;
- BeanPostProcessor的后置处理;
一些其他注解
-
@Import:用来导入其他配置类。 -
@ImportResource:用来加载xml配置文件。 -
@Value:注入Spring bootapplication.properties配置的属性的值。
@Value(value = “#{message}”) private String message;
@ExceptionHandler(Exception.class):用在方法上面表示遇到这个异常就执行以下方法。
源码学习
@Component www.cnblogs.com/wolf-bin/p/…