spring学习用笔记spring_day02
- 格式:doc
- 大小:41.00 KB
- 文档页数:16
spring学习用笔记spring_day02Spring_day02 2007-12-05 星期三一 , IOC 补充:1, 继承关系:<bean id="abstractBean" class="day02.ioc7.SomeBean" abstract="true"> <property name="str1"><value>string1</value></property><property name="num"><value>20</value></property></bean><!-- 继承关系 --><bean id="someBean" parent="abstractBean"><property name="num"><value>30</value></property></bean>得到的bean不想用单例时, 在bean标签上加 Scope=singleton/prototype 二, bean的生命周期(组件的装配过程):初始化(调用默认的构造器实例化,但是属性还没有赋值)---> 装配(设置依赖注入,给bean设置属性值)---> BeanNameAware 接口方法: setBeanName(); 如果bean实现了这个接口, 便会传递bean的名字给bean;---> BeanFactoryAware: setBeanFactory() ; 传递BeanFactory 给bean;---> ApplicationContextAware: setApplicationContext(); 传递ApplicationContext给bean;---> BeanPostProcessor:后处理bean;两个方法,postProcessAfterInitialization(Object bean, StringbeanName);Object postProcessBeforeInitialization(Object bean, StringbeanName)容器可以借助后处理bean对所有的其他bean作拦截, 相当于扩充了容器的功能;SomeBean实现了这个接口: 会对其他bean: A, B, C 的初始化或其他方法做拦截处理;---> common init()---> InitializingBean : void afterPropertiesSet() ; 初始化之后设置属性初始化:<1>. bean实现InitializingBean接口;<2>. 在配制文件中配置init-method="初始化方法",这个初始化方法定义在bean类中方法名不做要求;---> BeanPostProcessor: postProcessAfterInitialization---> common destroy()---> DisposableBean: destroy() ; 销毁之前;销毁:<1>. bean实现DisposableBean接口;<2>. 在配制文件中配置destroy-method="销毁方法",这个销毁方法定义在bean类中方法名不做要求;<1>. ApplicationContext:对于单例对象预先实例化,而对于一般的对象,只有在调用getBean()时才实例化;<2>. 后处理bean:1,实现了BeanPostProcessor接口的bean;2,在调用其他bean之前,会做一个指定的特殊处理;注:如果发现有一个bean实现了BeanPostProcessor接口, 就会当成特殊的bean 来处理;会对其他bean的属性进行处理 : 方法里写的内容;对于实现了BeanPostProcessor 接口的bean, 容器会扫描并自动注册为一个后处理bean,用来对其他bean做后处理, 在初始化之前, 之后做拦截;例子: ioc9客户端调用 getBean 时, 先调用默认构造器, 装配, 后处理;写一个初始化方法: init() 和销毁方法destroy()初始化: init-method="init" destroy-method="destroy"init 方法调用了, 但是destroy方法没有调用;AbstractApplicationContext ctx;//调用业务方法;ctx.registerShutdownHook(); //让容器调用destroy方法;1)对于单例类型的bean起作用, 没有设置scope="prototype"2)对非web应用起作用;2, bean工厂后处理: 例子: ioc9BeanFactoryPostProcessor:在容器读完所以的配置文件信息之后, 会调用实现了BeanFactoryPostProcessor接口的bean来做处理,bean还没有实例化之前被调用;还需要在配置文件中注册;例子:<bean id="myBeanPProcessor" class="day02.ioc9.MyBeanPostProcessor" />PropertyPlaceholderConfigurer : 是BeanFactoryPostProcessor的一个实现类;作用:分散配制,可以单独配置;<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfi gurer"><property name="location"><!--父类中有一个setLocation方法 --><value>配置文件的位置(ioc9\someinfo.properties)</value></property></bean>分散配置, ${database.driver_class} // 在配置文件database.properties 中有;例子:<bean id="someBean" class="day02.ioc9.SomeBean" init-method="init"destroy-method="destroy"><property name="str1"><value>${info}</value></property></bean><bean id="myBeanFactoryPProcessor"class="org.springframework.beans.factory.config.PropertyPlaceholderC onfigurer"><property name="location"><value>day02\ioc9\someinfo.properties</value></property></bean>3, 属性编辑:org.springframework.beans.factory.config.CustomEditorConfigurer属性编辑器:public class AddressEditor extends java.beans.PropertyEditorSupport{ @Overridepublic void setAsText(String arg0) throws IllegalArgumentException { // TODO Auto-generated method stubString[] strs = arg0.split("-");Address a = new Address();a.setCity(strs[0]);a.setRoom(Integer.parseInt(strs[1]));setValue(a);}配置文件:<bean id="person" class="day02.ioc10.Person"><property name="name"><value>zhangshan</value></property><property name="address"><value>beijing-188</value></property></bean><bean id="myCustomerEditor"class="org.springframework.beans.factory.config.CustomEditorConfigur er"><property name="customEditors"><map><entry key="day02.ioc10.Address"><!-- 定义关联关系--><bean id="myEditor" class="day02.ioc10.AddressEditor" /></entry></map></property></bean>三, 事件处理模式:1)自定义事件,通过继承org.springframework.context.ApplicationEventpublic class RegisterEvent extends ApplicationEvent{public RegisterEvent(Object source) {super(source);}}2)自定义监听器,实现org.springframework.context.ApplicationListener,并注册public class RegisterListener implements ApplicationListener{public void onApplicationEvent(ApplicationEvent arg0) {if(arg0 instanceof RegisterEvent){System.out.println("kill");}}3)发布事件,为得到应用上下文,需要在配置文件配置;必须实现org.springframework.context.ApplicationContextAware接口//相当于事件源,会定义注册监听器和解除的方法public class RegisterService implements ApplicationContextAware { private ApplicationContext ctx;public void register(String user){ //发布事件if(user.equals("csb")){ctx.publishEvent(new RegisterEvent(this));//在构造器中加一个参数:name}else{System.out.println(user+"register success");}}public void setApplicationContext(ApplicationContext arg0)throws BeansException {ctx=arg0;}}配置文件:<bean id="registerService" class="day02.ioc11.RegisterService"/> <bean id="registerListener" class="day02.ioc11.RegisterListener"/> 测试类:public static void main(String[] args) {ApplicationContext ctx= newClassPathXmlApplicationContext("/day02/ioc11/applicationContext.xml" );RegisterService rs = (RegisterService)ctx.getBean("registerService");rs.register("csb");//kill}四, AOP1, 什么是AOP ?面向方面/切面的编程:将程序中的交叉业务逻辑(公用代码)提取出来,称为切面,将这些切面动态的织入到目标对象,生成一个新的代理对象的过程;把程序划分为两部分:1) 通用的交叉业务,公用的代码(日志,事务,安全);2) 具体的业务逻辑处理代码;将切面动态的织入到业务代码中;2, AOP中的基本概念:1)切面(Aspect): 指交叉业务逻辑的统称, 比如日志,事务,安全;2)通知(Advice): 指切面的具体实现;3)连接点(Joinpoint):指切面可以织入到(应用到)目标对象的位置(级别), 两个: 方法/属性代理模式, 调用的是代理对象, 代理维护一个目标对象的属性;调用方法之前, 先写日志; 再调用具体的实现方法;调用属性之前, 拦截一下做处理,很少用;Spring目前不支持这个;4)切入点(Pointcut):指通知(切面的具体实现)应用到哪些目标对象的哪些方法或者哪些属性上;org.springframework.aop.PointcutSpring根据类名称及方法名称定义Pointcut,表示Advice织入至应用程序的时机;5)引入(introduction):指动态的给一个对象增加方法或者属性的过程;是一种特殊的通知;6)织入(weaving):将切面(通知)应用到目标对象生成代理的过程;7)代理对象(Proxy): 目标对象应用切面以后生成的代理(切面织入之后生成的新的代理对象);8)目标对象(Target): 具体业务逻辑的实现(需要织入切面的对象);3, Spring的AOP, 使用的是动态代理;1) 代理的两种方式:静态代理:针对每个具体类分别编写代理类;针对一个接口编写一个代理类;IRegisterRegisterService <--- RegisterProxy目标对象代理对象IRegister ir; 调用代理的方法, 代理再去调用目标对象的方法;IReportReportService <--- ReportProxy目标对象代理对象每一个代理对象只为一个目标对象服务;动态代理:针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类告诉一个类,我的接口是什么, 目标类是什么, 自动生成代理;2) 动态代理例子:public class MyProxyCreater implementsng.reflect.InvocationHandler {private Object target;public MyProxyCreater(Object target) {super();this.target = target;}public static Object createProxy(Object o){//类加载器,实现的接口,代理生成的类//根据三个参数创建一个代理对象;//通过类加载器,借口,和实现类得到一个代理对象//目标对象最少要实现一个接口return Proxy.newProxyInstance(o.getClass().getClassLoader(),o.getClass().getInterfaces(),new MyProxyCreater(o));}//代理对象,目标方法,目标对象的参数public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object rst=null;//加切面System.out.println("loging...");rst=method.invoke(target, args);return rst;}}spring思想:1,将切面使用动态代理的方式动态地织入到目标对象(被代理对象)生成新的代理对象;2,目标对象如果没有实现代理接口,spring采用CGLIB来生成代理对象,该代理对象是目标对象的子类;3,目标对象如果是final类,并且没有实现代理接口,就不能运用AOP了;目标对象如果没有实现接口, spring采用CGLIB库来动态生成一个代理, 代理是目标对象的子类; 目标对象不能是final的;Spring采用动态代理来实现AOP, 在运行时,spring将切面应用到目标对象生成动态代理,客户端使用动态代理来调用;AspectJ: 需要学习一些别的语言,支持属性连接点; 可以在编译期生成代理; 需要把编译器重新写一遍;难度比较大;3) Advice :切面的实现:类型:(1)org.springframework.aop.MethodBeforeAdvice在方法调用之前,做处理。