mybatis动态代理和spring对象注入

mybatis动态代理

实现方式:jdk通过proxy()动态代理产生mapper的代理对象
1.创建一个mapper;

import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;

public interface FriendMapper {
    @Select("select *from tb_friend")
    public List<Map<String,Object>> query();
}

2.重写 InvocationHandler的invoke方法
invoke里面包括获取sql,解析sql;

import org.apache.ibatis.annotations.Select;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class HnuInvohander implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //获取sql
       Select a= method.getAnnotation(Select.class);
       String sql=a.value()[0];
        //解析sql....
        System.out.println("sql----"+sql);
        return null;
    }
}

3.使用Proxy创建object对象
newProxyInstance有三个参数,第一个Class对象的类装载器,第二个“类”类型数组,第三个产生一个HnuInvohander对象

import java.lang.reflect.Proxy;
public class HnuSession  {
    public static Object getMapper(Class clazz){
        Class []clazzs=new Class[]{clazz};
        Object object=Proxy.newProxyInstance(HnuSession.class.getClassLoader(),clazzs,new HnuInvohander());
    return object;
    }
}

4.测试,调用object对象的方法

import com.hnu.mapper.FriendMapper;
import com.hnu.mybatis.HnuSession;
public class Test {
    public static void main(String[] args) {
      FriendMapper friendMapper= (FriendMapper) HnuSession.getMapper(FriendMapper.class);
      friendMapper.query();
    }
}

spring对象注入

第一种方式:使用@Bean注入
1.创建一个类,将mybatis动态代理产生的对象@Bean方式注入

import com.hnu.mapper.FriendMapper;
import com.hnu.mybatis.HnuSession;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.hnu")
@Configuration
public class Appconfig {
    @Bean
    public FriendMapper friendMapper(){
        FriendMapper friendMapper= (FriendMapper) HnuSession.getMapper(FriendMapper.class);
        return friendMapper;
    }
}

2.创建Service类,调用friendMapper方法,此时已经使用@Bean方式将friendMapper注入到容器当中了;

import com.hnu.mapper.FriendMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class FriendService {
    @Autowired
    FriendMapper friendMapper;
    public void queryAll(){
        friendMapper.query();
    }
}

3.测试,在容器中使用Service的方法;

import com.hnu.app.Appconfig;
import com.hnu.service.FriendService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Appconfig.class);
      ac.getBean(FriendService.class).queryAll();

第二种方法:实现FactoryBean接口,它会返回两个bean对象
一个是实现接口的类本身,另一个重写方法所产生的的对象
1.扫描com.hnu中带有@Component的包

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.hnu")
@Configuration
public class Appconfig {}

2.创建一个对象,也可以直接使用动态代理所产生的的对象;

public class Haaa {
    public Haaa(){
    }
}

3.实现 FactoryBean接口并重写方法;

import com.hnu.service.Haaa;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;
@Component
public class CJFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new Haaa();
    }
    @Override
    public Class<?> getObjectType() {
           //可以在这里直接使用动态代理产生的对象
           // FriendMapper friendMapper= (FriendMapper) HnuSession.getMapper(FriendMapper.class);
           //return friendMapper.class;
        return Haaa.class;
    }
    @Override
    public boolean isSingleton() {
        return false;
    }
}

4.测试,在容器中获取产生的bean。

import com.hnu.app.Appconfig;
import com.hnu.service.Haaa;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Appconfig.class);
        System.out.println(ac.getBean("CJFactoryBean"));
        System.out.println(ac.getBean("&CJFactoryBean"));
        System.out.println(ac.getBean(Haaa.class));
        }
}

第三种方式
spring中bean的注入方式也是采用这种方法,一般spring的bean的配置如下;

 <bean id="FridendMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface"value="com.hnu.mapper.FriendMapper">
    </property>
  </bean>

下面就是模拟spring注入bean:
实例化对象:
普通类实例化方式:class–>new
spring实例化方式:class–>scan扫描–>BeanDefinnition的方法–>生成map–>遍历map–>new bean
具体实现:通过实现FactoryBean和ImportBeanDefinitionRegistrar接口
1.实现FactoryBean接口重写方法,并定义一个可传参(参数就是需要注入的对象)的构造函数;

import org.springframework.beans.factory.FactoryBean;
public class CJFactoryBean implements FactoryBean {
    Class mapperInterface;
    public CJFactoryBean(Class mapperInterface){
        this.mapperInterface=mapperInterface;
    }
    @Override
    public Object getObject() throws Exception {
        Object object=  HnuSession.getMapper(mapperInterface);
        return object;
    }
    @Override
    public Class<?> getObjectType() {
        return mapperInterface;
    }
    @Override
    public boolean isSingleton() {
        return false;
    }
}

2.实现ImportBeanDefinitionRegistrar接口重写方法,BeanDefinition方法中有很多管理对象的方法,此处是指定生成一个对象,并将它传给CJFactoryBean的构造函数;

import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class CJImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        //指定构造方法的参数
        BeanDefinitionBuilder builder=BeanDefinitionBuilder.genericBeanDefinition(CJFactoryBean.class);
        AbstractBeanDefinition beanDefinition= builder.getBeanDefinition();
//传入的mapper都可以通过遍历循环产生
       beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("com.hnu.mapper.FriendMapper");
        beanDefinitionRegistry.registerBeanDefinition("CJFactoryBean",beanDefinition);
    }
}

3.创建一个类,导入识别CJImportBeanDefinitionRegistrar.class,并扫描包;

import com.hnu.mybatis.CJImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@ComponentScan("com.hnu")
@Configuration
@Import(CJImportBeanDefinitionRegistrar.class)
public class Appconfig {
}

4.创建Service类,调用friendMapper方法

import com.hnu.mapper.FriendMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class FriendService {
    @Autowired
    FriendMapper friendMapper;
    public void queryAll(){
        friendMapper.query();
    }
}

5.在容器中使用Service的方法。

import com.hnu.app.Appconfig;
import com.hnu.service.FriendService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Appconfig.class);
      ac.getBean(FriendService.class).queryAll();

你可能感兴趣的:(开发框架)