zoukankan      html  css  js  c++  java
  • spring FactoryBean接口

    这个接口有以下几个方法

    获取真实的对象

    T getObject() throws Exception;

    获取真实的对象的class对象

    Class<?> getObjectType();

    是不是单例

    boolean isSingleton();

    在使用过程中我们可以通过实现这个接口的几个方法,来创建一个类型为其它类型的bean

    主要是通过getObjectType()方法来实现。

    而且通常配合着动态代理来使用,这样就能够通过注入target的方式,将target对象代理上,并且创建出相应的对象。

    看下面一个例子:

    先创建一个实现了FactoryBean接口的MyFactoryBean

    package demo;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.InitializingBean;
    
    public class MyFactoryBean implements FactoryBean<Object>, InitializingBean, DisposableBean {
        private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class);
        private String interfaceName = "demo.DemoService";
        private Object target;
        public String getInterfaceName() {
            return interfaceName;
        }
    
        public void setInterfaceName(String interfaceName) {
            this.interfaceName = interfaceName;
        }
    
        public Object getTarget() {
            return target;
        }
    
        public void setTarget(Object target) {
            this.target = target;
        }
    
        public Object getProxyObj() {
            return proxyObj;
        }
    
        public void setProxyObj(Object proxyObj) {
            this.proxyObj = proxyObj;
        }
    
        private Object proxyObj;
    
        public Object getObject() throws Exception {
             return proxyObj;
        }
    
        public Class<?> getObjectType() {
            return proxyObj.getClass();
        }
    
        public boolean isSingleton() {
            return true;
        }
    
        public void afterPropertiesSet() throws Exception {
            proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    new Class[] { Class.forName(interfaceName) }, new InvocationHandler() {
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            logger.info("invoke method......" + method.getName());
                            logger.info("invoke method before......" + System.currentTimeMillis());
                            Object result = method.invoke(target, args);
                            logger.info("invoke method after......" + System.currentTimeMillis());
                            return result;
                        }
                    });
    
        }
    
        public void destroy() throws Exception {
            logger.info("destroy......");
    
        }
    }

    这里面除了实现了FactoryBean接口以外,还实现了InitializingBean接口,也就是说spring启动的时候会调用

    afterPropertiesSet方法

    这样就将target与代理对象绑定到了一起,因为当方法调用的时候会先执行一些代理自己的内容,在方法invoke之前和之后,invoke执行的是target对象的具体方法

    看一下具体调用

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                    new String[] { "spring/consumer.xml" });
            context.start();
            System.out.println("consumer start !");
    //        Person person = context.getBean("person",Person.class);
            
    //        DemoService demoService = context.getBean(DemoService.class);
            DemoService bean = (DemoService)context.getBean("myFactoryBean");
            bean.sayHello("sina");

    再看一下配置文件

    <bean id="myRealBean" class="demo.DemoServiceImpl"></bean>
        <bean id="myFactoryBean" class="demo.MyFactoryBean" >
            <property name="target" ref="myRealBean" />
        </bean>

    可以看到target是注入到MyfactoryBean里面的

    再看一下Mbatis的一个具体的例子

    public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
    
    public void afterPropertiesSet() throws Exception {
        notNull(dataSource, "Property 'dataSource' is required");
        notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
        state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
                  "Property 'configuration' and 'configLocation' can not specified with together");
    
        this.sqlSessionFactory = buildSqlSessionFactory();
      }
    public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
          afterPropertiesSet();
        }
    }

    可以看到mybatis在启动的时候会调用

     buildSqlSessionFactory()

    来创建sqlSessionFactory

    在getObject的时候在将创建了的sqlSessionFactory返回。这样就可以直接把SqlSessionFactoryBean定义为一个spring的一个bean供使用了

  • 相关阅读:
    怎样使用 Apache ab 以及 OneAPM 进行压力測试?
    opencv之haar特征+AdaBoos分类器算法流程(三)
    分区函数Partition By的与row_number()的用法以及与排序rank()的用法详解(获取分组(分区)中前几条记录)
    REST API 调用 方法
    WebApi的安全性及其解决方案
    使用Topshelf创建Windows服务
    LINQ查询操作符之First、FirstOrDefault、Last、LastOrDefault、ElementAt、ElementAtOrDefault、Contains、Any、All、Count
    sqlbulkcopy 多表批量保存
    C#使用HttpWebRequest和HttpWebResponse上传文件示例
    C#模拟客户端发送数据示例
  • 原文地址:https://www.cnblogs.com/liguangming/p/9973614.html
Copyright © 2011-2022 走看看