springdatajpa扩展

factorybean

1.当目标对象没有公共无参构造器时,使用factorybean向spring注册,它主要是用于在集成一些框架的时候。框架中的核心类我们并没有提供公共无参的构造器。
2.在spring配置文件中配置factorybean,通过factorybean向spring注册new TestFactoryBean()
3.当使用
@autowired
private TestFactoryBean testFactoryBean
注入对象时spring会调用MyfactoryBean中的getObject方法,获得对象

//在spring配置文件中配置factorybean
//id为通过factorybean向spring注册的对象
<bean class="com.wal.commom.MyFactoryBean" id="testFactoryBean"/>
public class MyFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        System.out.println("==================");
        return new TestFactoryBean();
    }

    @Override
    public Class<?> getObjectType() {
        return TestFactoryBean.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

initializationBean接口

如果向spring注册的对象实现了initializationBean接口,在spring容器初始化的时候会执行该对象的afterpropertiesSet方法

1.simplejparepository是通过JpaRepositoryFactoryBean向spring注册的,JpaRepositoryFactoryBean实现了initializationBean接口

2.simplejparepository结构图在这里插入图片描述
3.JpaRepositoryFactoryBean结构图

在这里插入图片描述
4.创建扩展接口

//这个注解的作用是不在springdatajpa初始化时不给改接口创建代理对象
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T,ID> , JpaSpecificationExecutor<T> {
   //扩展的方法
    //返回分页对象
    Page findByPageQuery(BaseQuery baseQuery);

    //返回不分页数据 按条件查询
    Page<T> findByQuery(BaseQuery baseQuery);

    //根据jpql查找
    List<T> findByJpqlQuery(String jpql,Object...values);
}

5.创建扩展接口的实现类

public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T,ID> implements IBaseRepository<T,ID> {
    //要spring把entitymanager通过构造方法传过来
    //spring底层默认是通过jparepositoryfactorybean 把entitymanager传给simpljparepository
    //所以我们要写一个baserepositoryfactorybean 告诉jpa:repositories 使用我们自己写的工厂类
    //baserepositoryImpl通过自己写的工厂类,向spring注册,spring在产生实例的时候会调用构造方法创建对象
    //默认情况下想spring注册的是simpljparepository
    private final EntityManager entityManager;

    public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
        this.entityManager=em;
    }

    @Override
    public Page<T> findByPageQuery(BaseQuery baseQuery) {
        baseQuery.creatPage();

        return super.findAll(baseQuery.getPageRequest());
    }

    @Override
    public Page<T> findByQuery(BaseQuery baseQuery) {
        baseQuery.creatPage();

        Specification specification = baseQuery.creatSpecification();
        return super.findAll(specification,baseQuery.getPageRequest());
    }

    @Override
    public List<T> findByJpqlQuery(String jpql, Object... values) {
        Query query = entityManager.createQuery(jpql);
        for (int i = 1; i <=values.length ; i++) {
            query.setParameter(i, values[i-1]);
        }
        return query.getResultList();
    }
}

6.创建BaseRepositoryFactoryBean

public class MyBaseRepositoryFactoryBean<T extends Repository<S,ID>,S,ID extends Serializable>
        extends JpaRepositoryFactoryBean<T,S,ID> {
    @Override
    //spring 初始化的时候会调用到这个方法(向spring注册的bean实现了initralizableBean接口)
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new MyRepositoryFactory<>(entityManager);
    }

    private static class MyRepositoryFactory<T,ID extends Serializable> extends JpaRepositoryFactory{
        private EntityManager entityManager;
        public MyRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager=entityManager;
        }

        @Override
        //spring最终获得的实现类
        protected Object getTargetRepository(RepositoryInformation information) {
            return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
        }

        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }
}

因为BaseRepositoryFactoryBean继承JpaRepositoryFactoryBean
JpaRepositoryFactoryBean实现了initializationBean接口,所以在spring容器初始化是,initializationBean接口中的afterpropertiesSet方法会被执行,该方法最终会调用到JpaRepositoryFactoryBean中的createRepositoryFactory方法
所以在BaseRepositoryFactoryBean中复写JpaRepositoryFactoryBean中的createRepositoryFactory方法
就是拦截,simplejparepository通过JpaRepositoryFactoryBean向spring注册的过程,复写createRepositoryFactory向spring注册自己需要的实现类BaseRepositoryImpl
6.更改springdatajpa的配置

<!--springdatajpa配置-->
    <jpa:repositories base-package="com.wal.aisell.repository"
                      entity-manager-factory-ref="entityManagerFactory"
                      transaction-manager-ref="transactionManager"
                        factory-class="com.wal.aisell.repository.impl.MyBaseRepositoryFactoryBean"/>

调用过程

1.spring容器初始化是调用afterPropertiesSet()方法
JpaRepositoryFactoryBean调用父类的afterPropertiesSet()
在这里插入图片描述
在这里插入图片描述
2.this.createRepositoryFactory()调用
在这里插入图片描述
3.this.doCreateRepositoryFactory();调用
在这里插入图片描述
4.这里就是要复写的方法在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值