• Spring积累


    <tx:annotation-driven/>  (Spring的XML配置里两大Bean的声明之一)


    那我们是否就可以在程序中所有被spring管理的类(@Controller、@Service、@Component等等)上都可以使用@Transactional注解了呢,在Service上可以使用@Transactional 注解这个是肯定的了,那总有些人也想弄明白能否在Controller 使用?答案显然是“不一定”的(与时间配置有关),下面做下解释:

    在 spring-framework-reference.pdf 文档上有这样一段话:

    <tx:annotation-driven/> only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put <tx:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services. 

    意思就是:<tx:annoation-driven/>只会查找和它在相同的应用上下文件中定义的bean上面的@Transactional注解,如果你把它放在Dispatcher的应用上下文中,它只检查控制器(Controller)上的@Transactional注解,而不是你services上的@Transactional注解。

    Bean初始化


    总结:

    1、Spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中通过init-method指定,两种方式可以同时使用。

    2、实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率要高一点,但是init-method方式消除了对spring的依赖。

    3、如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。

    后置处理器:


    BeanPostProcessor API
    public interface BeanPostProcessor {  
      
        /** 
         * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean 
         * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} 
         * or a custom init-method). The bean will already be populated with property values.    
         */  
        //实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务  
        Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
      
          
        /** 
         * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean 
         * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}   
         * or a custom init-method). The bean will already be populated with property values.       
         */  
        //实例化、依赖注入、初始化完毕时执行  
        Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
      
    }

    由API可以看出:
    1:后置处理器的postProcessorBeforeInitailization方法是在bean实例化,依赖注入之后及自定义初始化方法(例如:配置文件中bean标签添加init-method属性指定Java类中初始化方法、
    @PostConstruct注解指定初始化方法,Java类实现InitailztingBean接口)之前调用
    2:后置处理器的postProcessorAfterInitailization方法是在bean实例化、依赖注入及自定义初始化方法之后调用
    注意:
    1.BeanFactory和ApplicationContext两个容器对待bean的后置处理器稍微有些不同。ApplicationContext容器会自动检测Spring配置文件中那些bean所对应的Java类实现了BeanPostProcessor
    接口,并自动把它们注册为后置处理器。在创建bean过程中调用它们,所以部署一个后置处理器跟普通的bean没有什么太大区别。

          2.BeanFactory容器注册bean后置处理器时必须通过代码显示的注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法

    注意:
    1.BeanFactory和ApplicationContext两个容器对待bean的后置处理器稍微有些不同。ApplicationContext容器会自动检测Spring配置文件中那些bean所对应的Java类实现了BeanPostProcessor
    接口,并自动把它们注册为后置处理器。在创建bean过程中调用它们,所以部署一个后置处理器跟普通的bean没有什么太大区别。

          2.BeanFactory容器注册bean后置处理器时必须通过代码显示的注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法

    /**  
         * Add a new BeanPostProcessor that will get applied to beans created  
         * by this factory. To be invoked during factory configuration.  
         * <p>Note: Post-processors submitted here will be applied in the order of  
         * registration; any ordering semantics expressed through implementing the  
         * {@link org.springframework.core.Ordered} interface will be ignored. Note  
         * that autodetected post-processors (e.g. as beans in an ApplicationContext)  
         * will always be applied after programmatically registered ones.  
         * @param beanPostProcessor the post-processor to register  
         */    
        void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

     Spring如何调用多个BeanPostProcessor实现类:

        我们可以在Spring配置文件中添加多个BeanPostProcessor(后置处理器)接口实现类,在默认情况下Spring容器会根据后置处理器的定义顺序来依次调用。

    Spring配置文件:

     xml版本

      

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- bean定义 -->    
        <bean id="narCodeService" class="com.test.service.impl.NarCodeServiceImpl">
        </bean>
        <bean id="postProcessor" class="com.test.spring.PostProcessor"/>
        <bean id="postProcessorB" class="com.test.spring.PostProcessorB"/>
    </beans>

    BeanPostProcessor实现类:

    package com.test.spring;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    /**
     * bean后置处理器
     * @author zss
     *
     */
    public class PostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器处理bean=【"+beanName+"】开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器处理bean=【"+beanName+"】完毕!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    }
    ----------------------------------------------------------------------------------------------------------------------------------------
    package com.test.spring;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    public class PostProcessorB implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器开始调用了");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器调用结束了");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    }

    测试:

    package com.test.spring;
    
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class T {
        AbstractApplicationContext applicationcontext=null;
        @Before
        public void before() {
            System.out.println("》》》Spring ApplicationContext容器开始初始化了......");
            applicationcontext= new ClassPathXmlApplicationContext(new String[]{"test1-service.xml"});
            System.out.println("》》》Spring ApplicationContext容器初始化完毕了......");
        }
        @Test
        public void  test() {
            applicationcontext.registerShutdownHook();   
        }
    }

      在Spring机制中可以指定后置处理器调用顺序,通过让BeanPostProcessor接口实现类实现Ordered接口getOrder方法,该方法返回一整数,默认值为 0,优先级最高,值越大优先级越低

    package com.test.spring;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.core.Ordered;
    /**
     * bean后置处理器
     * @author zss
     *
     */
    public class PostProcessor implements BeanPostProcessor,Ordered{
    
        @Override
        public Object postProcessBeforeInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器处理bean=【"+beanName+"】开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器处理bean=【"+beanName+"】完毕!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    
        @Override
        public int getOrder() {
            return 1;
        }
    }
    ----------------------------------------------------------------------------
    package com.test.spring;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.core.Ordered;
    
    public class PostProcessorB implements BeanPostProcessor,Ordered {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器开始调用了");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean,
                String beanName) throws BeansException {
            System.out.println("后置处理器调用结束了");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return bean;
        }
    
        @Override
        public int getOrder() {
            return 0;
        }
    }

    测试结果:

  • 相关阅读:
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    MFC/.NET
    学习小结——记于华为2018届校园招聘宣讲会之后
    槽点今天未想到
  • 原文地址:https://www.cnblogs.com/toov5/p/10614359.html
Copyright © 2020-2023  润新知