Spring动态代理的两种方式
总结
一个典型的动态代理创建对象过程可分为以下四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newProxyInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))
cglib动态代理是生成被代理类的子类,并覆盖其中方法进行增强。
深入理解事务--Spring事务的传播机制
Spring service本类中方法调用另一个方法事务不生效问题
spring事务传播机制实例讲解
事务嵌套:两个事务方法之间相互调用。同一个类中的方法调用事务方法不生效,是因为事务切面。
通过spring注入的类是代理类,代理类会有事务切面,但是原来的类只是普通的类,调用它的方法就只是简单执行它的方法而已。
spring默认情况下会对uncheck异常(运行时异常)进行事务回滚;checked不回滚。
改变默认规则
rollbackFor=Exception.class
notRollbackFor=
事务传播属性
Spring五个事务隔离级别和七个事务传播行为
定义事务的控制范围。
支持:
不支持当前事务:
嵌套:
ioc:控制反转,也是依赖注入。将对象交给容器控制来注入对象。
配置好bean后,由容器给我们注入bean
用反射实现。
通过解析xml文件或java配置,获取到beanid和class属性内容,利用反射,通过class.forName获得class对象再来实例化对象,然后将它放进spring的bean容器中。
通过反射实例化对象,存入到Spring的bean容器中。
当一个类需要另一个类时,从容器中获取到对应的bean对象,获取类的setter方法的Method类,setter调用invoke方法执行,注入之前拿到的bean对象。
aop:反射+动态代理
Spring aop的实现原理
面向切面编程,在一个地方定义通用功能,可以通过声明的方式定义这个功能在类的哪里应用,而无需修改受影响的类。可将系统功能与核心业务逻辑相分离。(安全、日志、事务等)
通知:执行的工作
切点:连接点
切面:通知+切点
只支持方法级别的连接点(切点)
把切面应用到目标对象时动态创建一个代理类,拦截被通知方法的调用,执行切面逻辑。
动态代理主要是实现InvocationHandler,并且将目标对象注入到Handler中,利用反射机制来执行目标对象的方法。
proxy.newProxyInstance(对象的类加载器, 目标对象的接口, InvocationHandler);
InvocationHandler中的invoke,由代理类调用
public Object invoke(Object proxy 代理类, Method method 调用的方法, Object[] args 参数)
调用目标对象的方法
method.invoke(this.target, args);
bean的作用域
单例(singleton)
原型(prototype)
会话(session)代理,延迟注入
请求(resquest)
springmvc请求顺序
dispatcherServlet-->HandlerMapping
............................-->Controller-->Model/viewname
............................-->viewResolver-->view-->返回响应
所有请求通过dispatcherservlet前端控制器,dispatcherservlet查询一个或多个mappinghandler处理器映射,决定将请求发给哪个controller;
控制器处理完后产生信息model,将它打包并标示用于渲染输出的视图名。接下来将请求和信息发送回dispatcherservlet;
前端控制器使用viewresovler视图解析器将逻辑视图名匹配给一个特定的视图实现;
视图将model渲染输出,通过响应对象传递给客户端。
启动springmvc
@Configuration 配置类
@EnableWebMvc 启用springmvc
@ComponentScan("包") 开启组件扫描
ViewResolver{}
控制器
@Controller 类
@RequestMapping(value="/",method=RequestMethod.GET) 方法或类级别,value能接收一个String类型的数组
model
方法参数,返回string或其他值,会自动放进模型中,响应给 string链接或者返回json或请求路径(逻辑视图由请求路径推出)
查询参数
@RequestParam(value="max",defaultValue="3") long max,url上的查询参数
路径变量
@RequestMapping(value="/{max}")
@PathVariable(value="max") long max, 通过路径参数接受输入,资源通过url标识
重定向:"redirect:" flash属性通过会话中转
请求转发:"forward:"
校验表单:@NotNull、@Null、@Size等
应用:@Valid Lei lei,Error errors){ errors.hasErrors()}
web.xml中配置dispatcherservlet
异常
特定的spring异常会自动映射为指定的http状态码
@ExceptionHandler(XXException.class) 方法,同一类中的异常由这个方法处理
@ResponseBody 方法,将返回的对象转化为json
@RequestBody 参数,将Json转化为java对象
@RestController 类,@RequestBody+@ResponseBody
查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:
GET 请求可被缓存
GET 请求保留在浏览器历史记录中
GET 请求可被收藏为书签
GET 请求不应在处理敏感数据时使用
GET 请求有长度限制
GET 请求只应当用于取回数据
查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的:
POST 请求不会被缓存
POST 请求不会保留在浏览器历史记录中
POST 不能被收藏为书签
POST 请求对数据长度没有要求
幂等性??
spring 容器
负责创建对象,装配它们,配置并管理它们的整个生命周期。即对象由spring容器创建和装配,并存在容器中。
spring bean的生命周期
正确理解它非常重要,因为或许需要利用spring提供的扩展点来自定义bean的创建过程。
Spring默认实例化Bean的情况下,采用的是lazy机制,换言之,如果不通过getBean()方法(BeanFactory或者ApplicationContext的方法)获取Bean的话,那么为了节省内存将不实例话Bean,只有在Bean被调用的时候才实例化他们。
BeanPostProcessor如果有bean实现了这个接口,那么其他bean会调用这个bean实现的方法。
Spring Bean的生命周期(非常详细)
Spring各jar包作用及依赖
Maven构建的Spring项目需要哪些依赖?
** spring 各个jar详解以及在maven中的配置 **
maven常用插件解析