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.这里就是要复写的方法