Spring
它是为了解决软件开发的复杂性。把对象交给Spring进行管理,通过面向切面编程来实现一些"模板式"的操作,使得程序员有更多的精力去完成业务实现。
Spring解决对象之间依赖关系
bean容器注解
@Required, @Autowired, @PostConstruct, @PreDestory,还有Spring3.0开始支持的JSR-330标准javax.inject.*中的注解(@Inject, @Named, @Qualifier, @Provider, @Scope, @Singleton).
springmvc相关注解
@Controller, @RequestMapping, @RequestParam, @ResponseBody等等。
Spring的优点
方便解耦,简化开发 (高内聚低耦合)
Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理
spring工厂是用于生成bean
AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
声明式事务的支持
只需要通过配置就可以完成对事务的管理,而无需手动编程
方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
降低JavaEE API的使用难度
Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
Ioc和aop
AOP的实现,一种横向抽取机制,依赖于动态代理模式。
关于AOP的几个重点概念:
JoinPoint:连接点,说白了,就是可以被增强的方法;
PointCut:切入点,对哪些JoinPoint进行拦截;
Advice:通知,就是拦截后的动作;
Aspect:切面,把增强应用到具体方法的过程;
Spring的AOP需要借助aspectj来实现,可以通过XML,也可以通过注解来完成。
bean与spring容器的关系
https://www.cnblogs.com/wuchanming/p/5426746.html
Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。
bean配置
bean配置有三种方法:
- 基于xml配置Bean
- 使用注解定义Bean
- 基于java类提供Bean定义信息
Spring mvc
将视图和逻辑隔离开来
将web层的Servlet对象传递给处理方法。
静态代理
是指在程序运行前就已经存在的编译好的代理类是为静态代理。实现静态代理有四个步骤:
①定义业务接口;
②被代理类实现业务接口;
③定义代理类并实现业务接口;
④最后便可通过客户端进行调用。(这里可以理解成程序的main方法里的内容)
package com.zhb.jdk.proxy;
public class UserServiceProxy implements IUserService {
// 被代理对象
private IUserService target;
// 通过构造方法传入被代理对象
public UserServiceProxy(IUserService target) {
this.target = target;
}
@Override
public void add(String name) {
System.out.println("准备向数据库中插入数据");
target.add(name);
System.out.println("插入数据库成功");
}
}
静态代理缺点:
①代理类和被代理类实现了相同的接口,导致代码的重复,如果接口增加一个方法,被代理类和代理类都要实现这个方法,增加了代码维护的难度。
②代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。比如上面的例子,只是对用户的业务功能(IUserService)进行代理,如果是商品(IItemService)的业务功能那就无法代理,需要去编写商品服务的代理类。
动态代理:
在程序运行期间根据需要动态创建代理类及其实例来完成具体的功能。
动态代理主要分为JDK动态代理和cglib动态代理两大类
JDK动态代理
我们并没有像静态代理那样去自己定义一个代理类,并实例化代理对象。实际上,动态代理的代理对象是在内存中的,是JDK根据我们传入的参数生成好的。
cglib动态代理
JDK代理要求被代理的类必须实现接口,有很强的局限性。而CGLIB动态代理则没有此类强制性要求。简单的说,CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。
代理方式 | 实现 | 优点 | 缺点 | 特点 |
JDK静态代理 | 代理类与委托类实现同一接口,并且在代理类中需要硬编码接口 | 实现简单,容易理解 | 代理类需要硬编码接口,在实际应用中可能会导致重复编码,浪费存储空间并且效率很低 | 好像没啥特点 |
JDK动态代理 | 代理类与委托类实现同一接口,主要是通过代理类实现InvocationHandler并重写invoke方法来进行动态代理的,在invoke方法中将对方法进行增强处理 | 不需要硬编码接口,代码复用率高 | 只能够代理实现了接口的委托类 | 底层使用反射机制进行方法的调用 |
CGLIB动态代理 | 代理类将委托类作为自己的父类并为其中的非final委托方法创建两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法。在代理方法中,它会判断是否存在实现了MethodInterceptor接口的对象,若存在则将调用intercept方法对委托方法进行代理 | 可以在运行时对类或者是接口进行增强操作,且委托类无需实现接口 | 不能对final类以及final方法进行代理 | 底层将方法全部存入一个数组中,通过数组索引直接进行方法调用 |