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五个事务隔离级别和七个事务传播行为
定义事务的控制范围。
支持:- required:如果存在一个事务,则支持当前事务。如果没有则开启一个新的事务。默认
- supports:如果存在一个事务,支持当前事务。如果没有事务非事务的执行。
- mandatory:如果存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
不支持当前事务:
- requires_new:总是开启一个新的事务。如果存在则将这个事务挂起。子事务不会直接影响到父事务的提交和回滚。
- not_supported:总是非事务的执行,并挂起任何存在的事务。
- never:总是非事务的执行,如果存在一个活动事务,则抛出异常。
嵌套:
- nested:如果一个活动的事务存在,则运行在一个嵌套的事务中,如果不存在则新建事务。
子事务是父事务的一部分,由父事务统一提交。父事务回滚,子事务也会回滚。子事务回滚,会回到一个savepoint点。
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
<mvc:annotation-driven>注解启用
@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容器创建和装配,并存在容器中。
- bean工厂,是最简单的容器,提供基本的DI支持。
- 应用上下文,基于beanFactory构建,提供应用框架级别的服务,例如从属性文件解析文本信息以及发布应用事件给感兴趣的事件监听者。
spring bean的生命周期
正确理解它非常重要,因为或许需要利用spring提供的扩展点来自定义bean的创建过程。
Spring默认实例化Bean的情况下,采用的是lazy机制,换言之,如果不通过getBean()方法(BeanFactory或者ApplicationContext的方法)获取Bean的话,那么为了节省内存将不实例话Bean,只有在Bean被调用的时候才实例化他们。
-
实例化。
解析xml配置文件或java配置类,获取到beanid和class属性内容,利用反射,通过class.forName获得class对象再实例化对象。 -
填充属性。
当属性是另一个类是,从容器中获取到对应的bean引用,获取以实例化对象的setter方法的Method类,setter调用invoke方法执行,注入bean引用。(属性注入。构造器注入在实例化部分) -
调用BeanNameAware的setBeanName()方法
如果bean实现了BeanNameAware接口,会调用setBeanName,将bean的名字传给bean自己, -
调用BeanFactoryAware的setBeanFactory()方法
、、、、、传入beanFactory容器, -
调用ApplicationContextAware的setApplicationContext()方法
(用DefaultListableBeanFactory实现的容器实例化对象时不会调用ApplicationContextAware的方法)
、、、、、传入ApplicationContext容器 - 调用BeanPostProcessor的预初始化方法,即postProcessorBeforeInitialization()方法
-
调用InitializingBean的afterPropertiesSet()方法
如果bean使用init-method声明了初始化方法,也会调用
- 调用自定义的初始化方法 - 调用BeanPostProcessor的初始化后方法,即postProcessorAfterInitialization()方法
-
可以使用bean了,将一直驻留在应用上下文中,直到该应用上下文被销毁
容器关闭 -
调用DisposableBean的destory()方法
如果使用destroy-method声明了销毁方法,该也会被调用。
- 调用自定义的销毁方法
BeanPostProcessor如果有bean实现了这个接口,那么其他bean会调用这个bean实现的方法。
Spring各jar包作用及依赖
Maven构建的Spring项目需要哪些依赖?
** spring 各个jar详解以及在maven中的配置 **
网友评论