Spring @Enable原理解析,实现一个简单的MyFeginClient模块

 

 @EnableXXX在spring项目中很常见,下面看看它背后的原理,其实它的实现离不开spring bean的生命周期。

1、定义@MyFeginClientScanner注解,修饰接口,表示接口使用动态代理生成实例。

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyFeginClientScanner {
    String url() default "";
}

2、定义@MyFeginClientRequestMapping注解,修饰方法。

@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyFeginClientRequestMapping {
    String value() default "";
}

3、定义@EnableMyFeginClientAutoConfiguration注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(MyFeginClientAutofigurationRegistrar.class)
public @interface EnableMyFeginClientAutoConfiguration {
    String basePackage() default "";
    //设置代理类实现,默认为使用JDK动态代理
    Class<? extends AbstractMyFeginClientFactoryBean> implClass() default MyFeginClientFactoryBean.class;
}

4、创建MyFeginClientAutofigurationRegistrar和MyFeginClientClasspathScanner这两个主要功能是扫描basePackage包下         @MyFeginClientScanner注解的类解析为BeanDefinition。

public class MyFeginClientClasspathScanner extends ClassPathBeanDefinitionScanner {

    private static final Logger logger = LoggerFactory.getLogger(MyFeginClientClasspathScanner.class);

    private Class<? extends AbstractFactoryBean> factoryBeanImplClass;

    public MyFeginClientClasspathScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        //BeanDefinitionHolder 封装了BeanDefinition,beanName以及aliases
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        logger.info("find beanDefinitions :" + beanDefinitions);
        if (!beanDefinitions.isEmpty()) {
            for (BeanDefinitionHolder holder : beanDefinitions) {
                GenericBeanDefinition defination = (GenericBeanDefinition) holder.getBeanDefinition();
                defination.getPropertyValues().addPropertyValue("mapperInterface", defination.getBeanClassName());
                // 设置bean工厂和对应的属性值
                defination.setBeanClass(this.factoryBeanImplClass);
                defination.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            }
        }
        return beanDefinitions;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return (beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
        if (super.checkCandidate(beanName, beanDefinition)) {
            return true;
        } else {
            logger.warn("Skipping MapperFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface"
                    + ". Bean already defined with the same name!");
            return false;
        }
    }

    public void setFactoryBeanImplClass(Class<? extends AbstractFactoryBean> factoryBeanImplClass) {
        this.factoryBeanImplClass = factoryBeanImplClass;
    }

}
public class MyFeginClientAutofigurationRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

    private static final Logger logger = LoggerFactory.getLogger(MyFeginClientAutofigurationRegistrar.class);

    private Environment env;
    private ResourceLoader resourceLoader;

    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
        if (logger.isDebugEnabled()) {
            logger.debug("setEnvironment");
        }
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
        if (logger.isDebugEnabled()) {
            logger.debug("setResourceLoader");
        }
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        if (logger.isDebugEnabled()) {
            logger.debug("registerBeanDefinitions");
        }

        // 获取MyFeginClientScanner配置的basePackage
        AnnotationAttributes annoAttrs = AnnotationAttributes
                .fromMap(importingClassMetadata.getAnnotationAttributes(EnableMyFeginClientAutoConfiguration.class.getName()));
        String basePackage = annoAttrs.getString("basePackage");

        //使用implClass来切换代理实现方式
        //@EnableMyFeginClientAutoConfiguration(basePackage = "com.luna.springbootpractice.demo.service",implClass = MyFeginClientCgLibFactoryBean.class)
        Class<? extends AbstractFactoryBean> implClass = annoAttrs.getClass("implClass");

        // 扫描带有MyFeginClientScanner注解的接口
        MyFeginClientClasspathScanner scanner = new MyFeginClientClasspathScanner(registry);
        scanner.setResourceLoader(resourceLoader);
        scanner.addIncludeFilter(new AnnotationTypeFilter(MyFeginClientScanner.class));

        scanner.setFactoryBeanImplClass(implClass);
        scanner.doScan(basePackage);
    }

}

5、创建MyFeginClientSupport接口,接口DefaultMyFeginClientSupport,在这里可以处理请求。

public interface MyFeginClientSupport {
    Object invoke(Object proxy, Method method, Object[] args);
}

public class DefaultMyFeginClientSupport implements MyFeginClientSupport {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {

        MyFeginClientScanner myFeginClientScanner = method.getDeclaringClass().getAnnotation(MyFeginClientScanner.class);
        MyFeginClientRequestMapping myFeginClientRequestMapping = method.getAnnotation(MyFeginClientRequestMapping.class);

        if (myFeginClientRequestMapping == null) {
            return null;
        }

        String value = myFeginClientRequestMapping.value();
        String url = StringUtils.join(myFeginClientScanner.url(), value);

        String result = null;
        if (args != null && args.length == 1) {

            //发送http请求
            //Map<String,Object> params = new HashMap<String, Object>(1);
            //params.put("param",args[0]);
            //JSONObject jsonObject = HttpClientPoolUtil.doGet(url,params);

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("test", args[0]);

            result = jsonObject.toJSONString();
        }

        if (method.getReturnType() == String.class) {
            return result;
        }
        return null;

    }
}

6、创建动态代理的InvocationHandler实现类。

public class MyFeginClientInvocationHandler implements InvocationHandler {

    private MyFeginClientSupport myFeginClientSupport;

    public MyFeginClientInvocationHandler(MyFeginClientSupport myFeginClientSupport) {
        this.myFeginClientSupport = myFeginClientSupport;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return myFeginClientSupport.invoke(proxy,method, args);
    }
}

7、实现FactoryBean,先定义AbstractMyFeginClientFactoryBean然后再利用JDK动态代理和CGLIB代理生成实现类。

public class AbstractMyFeginClientFactoryBean<T> implements FactoryBean<T>, InitializingBean {

    @Autowired
    private MyFeginClientSupport myFeginClientSupport;

    private Class<?> mapperInterface;

    private T t;

    public void setProxyTarget(T t) {
        setT(t);
    }

    @Override
    public T getObject() throws Exception {
        return  t;
    }

    @Override
    public Class getObjectType() {
        return mapperInterface;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }

    public MyFeginClientSupport getMyFeginClientSupport() {
        return myFeginClientSupport;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public Class<?> getMapperInterface() {
        return mapperInterface;
    }

    public void setMapperInterface(Class<?> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }
}

 JDK动态代理FactoryBean:

public class MyFeginClientFactoryBean<T> extends AbstractMyFeginClientFactoryBean<T> {

    @SuppressWarnings("unchecked")
    @Override
    public void afterPropertiesSet() throws Exception {
        T target = (T) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { getMapperInterface() },
                new MyFeginClientInvocationHandler(getMyFeginClientSupport()) );
        setProxyTarget(target);
    }

}

 CGLIB代理FactoryBean:

public class MyFeginClientCgLibFactoryBean<T> extends AbstractMyFeginClientFactoryBean<T> implements MethodInterceptor {

    @SuppressWarnings("unchecked")
    @Override
    public void afterPropertiesSet() throws Exception {
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);
        enhancer.setSuperclass(getMapperInterface());
        setProxyTarget((T) enhancer.create());
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        return getMyFeginClientSupport().invoke(obj,method, args);
    }

}

8、创建测试service。

@MyFeginClientScanner(url = "http://localhost:80")
public interface TestMyFeginClientService {

    @MyFeginClientRequestMapping(value = "/test")
    public String test(String param);

}

9、运行测试类。

public class TestMyFeginClientServiceTest extends SpringbootpracticeApplicationTests {

    @Autowired
    private TestMyFeginClientService testMyFeginClientService;

    @Test
    public void test() {
        String result = testMyFeginClientService.test("test");
        System.out.println(result);
    }
}

输出:{"test":"test"}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值