Spring框架--注册代理类

最近我遇到了一个难题,如下图,禁止任何类继承A这个接口,而程序正常运行,怎么实现?

(换种问法,就是如何实现Mybatis的配置方式)

 

了解代理模式的,一看就知道,要使用动态代理的知识,但,问题的难点不在这;

难点是要把代理类,注册到Spring容器中,使用@Autowired可以获取到你的代理类。

(注:Spring注册需要的是Class,而不是一个对象实例;但是动态代理获取到的已经是对象实例)

 

Demo(往Spring容器注册代理类)

工厂类

使用了Cglib提供的代理方式

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class BeanFactory {
    /**
     * 代理方法回调
     * 
     * @author ChenSS on 2017年12月21日
     */
    private class MyInterceptor implements MethodInterceptor {
        private Class<?> clazz;

        @Override
        public Object intercept(Object obj, Method method, Object[] params, MethodProxy proxy) throws Throwable {
            String methodName = method.getName();
            if ("toString".equals(methodName) || "hashCode".equals(methodName)) {
                return proxy.invokeSuper(obj, params);
            }
            try {
                System.out.println("前置代理");
                System.out.println(clazz.getSimpleName() + " " + methodName + " invock");
                return null;
            } catch (Exception e) {
                System.out.println("异常代理");
                return null;
            } finally {
                System.out.println("后置代理");
            }
        }
    }

    /**
     * 创建代理类
     */
    public Object getInstance(Class<?> clazz) throws Exception {
        System.out.println("======================================");
        System.out.println(clazz + " create proxy...");
        MyInterceptor callBack = new MyInterceptor();
        callBack.clazz = clazz;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(callBack);
        Object obj = enhancer.create();
        System.out.println("======================================");
        return obj;
    }
}

普通类

public interface HelloWorld1 {
    public void sayHello();
}

public interface HelloWorld2 {
    public void sayHello();
}/**
 * 使用了Spring注解的Bean
 * 
 * @author ChenSS on 2017年12月21日
 */
@Component
public class TestBean {
    
    @Autowired
    HelloWorld1 helloWorld1;

    public HelloWorld1 getHelloWorld1() {
        return helloWorld1;
    }
}

Spring配置

注解和Xml混合使用

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
     http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-4.2.xsd
     http://www.springframework.org/schema/cache 
     http://www.springframework.org/schema/cache/spring-cache.xsd">

    <bean id="beanFactory" class="com.client.bean.BeanFactory"/>
        
    <bean id="helloWorld1" factory-bean="beanFactory" factory-method="getInstance">
        <constructor-arg type="Class"><value>com.client.bean.HelloWorld1</value></constructor-arg>           
    </bean>

    <bean id="helloWorld2" factory-bean="beanFactory" factory-method="getInstance" lazy-init="true">
        <constructor-arg type="Class"><value>com.client.bean.HelloWorld2</value></constructor-arg>           
    </bean>
        
    <!-- 自动注入,扫描包 -->
    <context:component-scan base-package="com.client.bean" />
</beans>

测试函数

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.client.bean.HelloWorld1;
import com.client.bean.HelloWorld2;
import com.client.bean.TestBean;

public class TestSp {
    public static void main(String[] args) throws InterruptedException {
        AbstractApplicationContext context = 
                new ClassPathXmlApplicationContext("classpath:config/spring_context.xml");
        
        //测试@Autowired注入功能
        TestBean bean =context.getBean(TestBean.class);
        HelloWorld1 helloWorld1 = bean.getHelloWorld1();
        helloWorld1.sayHello();

        //测试懒加载功能
        Thread.sleep(2000);
        System.out.println("Thread wait 2000ms");
        
        HelloWorld2 helloWorld2 = (HelloWorld2) context.getBean("helloWorld2");
        helloWorld2.sayHello();
        context.close();
    }
}

 

实际使用过程中,不一定要全部配写在Xml文件中,直接通过Java代码注册Bean,像Mybatis一样,写一份自动扫描包的方法

 

posted on 2017-12-21 21:55  疯狂的妞妞  阅读(205)  评论(0编辑  收藏  举报

导航