Dubbo的xml命名空间解析关键

在Spring中的applicationContext.xml经常看到如下标签





1.Dubbo创建了一个dubbo.xsd文件。
2.并为dubbo.xsd创建了另外两个文件:spring.handlers和spring.schemas(这是Spring的命名解析规范要求),Spring在解析过程中会主动搜索这两资源文件。

3.spring.handlers文件内容如下

http://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

4.spring.schemas文件内容如下

http://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

5.在执行下面代码时,会主动触发相关文件解析。

String configure = "provider-applicationContext.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(configure);



6.具体如下:

public class DubboNamespaceHandler extends NamespaceHandlerSupport {
	static {
		Version.checkDuplicate(DubboNamespaceHandler.class);
	}
	public void init() {
	    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
    }
}

7.上述步骤,已经完成了beanmap列表的建立,但仍需要下述代码,触发Dubbo的建立RPC服务,其中xxxConfig是在xxxBean之前先创建的。

context.start();
context.registerShutdownHook();

8.在6步骤中的的ServiceBean中监听了ApplicationEvent如下:

public void onApplicationEvent(ApplicationEvent event) {
        if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
        	if (isDelay() && ! isExported() && ! isUnexported()) {
                if (logger.isInfoEnabled()) {
                    logger.info("The service ready on spring started. service: " + getInterface());
                }
                会把xxxConfig的内容,初始化ServiceBean里的对象。
                export();
            }
        }
    }

9.serviceBean是多个的,每个service对象,对应一个,故每个对象都监听了ApplicationEvent。


    
    
    
    
    

动态 IP 、固定 IP 、实体 IP 与虚拟 IP

看到论坛中的一段介绍,感觉豁然开即朗的感觉,简单总结一下:
从个人感觉:外网IP就是真实IP,而内网IP或局域网IP就是虚拟IP。

以下是摘录别人的:

动态 IP 、固定 IP 、实体 IP 与虚拟 IP都讲解一下,加深理解和知识扩展

实体 IP:在网络的世界里,为了要辨识每一部计算机的位置,因此有了计算机 IP 位址的定义。一个 IP 就好似一个门牌!例如,你要去微软的网站的话,就要去『 207.46.197.101 』这个 IP 位置!这些可以直接在网际网络上沟通的 IP 就被称为『实体 IP 』了。

虚拟 IP:不过,众所皆知的,IP 位址仅为 xxx.xxx.xxx.xxx 的资料型态,其中, xxx 为 1-255 间的整数,由于近来计算机的成长速度太快,实体的 IP 已经有点不足了,好在早在规划 IP 时就已经预留了三个网段的 IP 做为内部网域的虚拟 IP 之用。这三个预留的 IP 分别为:

A级:10.0.0.0 – 10.255.255.255
B级:172.16.0.0 – 172.31.255.255
C级:192.168.0.0 – 192.168.255.255

上述中最常用的是192.168.0.0这一组。不过,由于是虚拟 IP ,所以当您使用这些地址的时候﹐当然是有所限制的,限制如下:

私有位址的路由信息不能对外散播
使用私有位址作为来源或目的地址的封包﹐不能透过Internet来转送
关于私有位址的参考纪录(如DNS)﹐只能限于内部网络使用

由于虚拟 IP 的计算机并不能直接连上 Internet ,因此需要特别的功能才能上网。不过,这给我们架设IP网络做成很大的方便﹐比如﹕即使您目前的公司还没有连上Internet﹐但不保证将来不会啊。如果使用公共IP的话﹐如果没经过注册﹐等到以后真正要连上网络的时候﹐就很可能和别人冲突了。也正如前面所分析的﹐到时候再重新规划IP的话﹐将是件非常头痛的问题。这时候﹐我们可以先利用私有位址来架设网络﹐等到真要连上intetnet的时候﹐我们可以使用IP转换协定﹐如 NAT (Network Addresss Translation)等技术﹐配合新注册的IP就可以了。

固定 IP 与 动态 IP:基本上,这两个东西是由于近来网络公司大量的成长下的产物,例如,你如果向中华电信申请一个商业型态的 ADSL 专线,那他会给你一个固定的实体 IP ,这个实体 IP 就被称为『固定 IP 』了。而若你是申请计时制的 ADSL ,那由于你的 IP 可能是由数十人共同使用,因此你每次重新开机上网时,你这部计算机的 IP 都不会是固定的!于是就被称为『动态 IP』或者是『浮动式IP』。基本上,这两个都是『实体IP』,只是网络公司用来分配给用户的方法不同而产生不同的名称而已

@resource和@Autowired的区别

@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配顺序
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

fastxml.json的序列化

专门分析一下fastxml.json的序列化,偶有所得,截图如下:


另一个示例

public class User {
    public interface WithoutPasswordView {};
    public interface WithPasswordView extends WithoutPasswordView {};

    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @JsonView(WithoutPasswordView.class)
    public String getUsername() {
        return this.username;
    }

    @JsonView(WithPasswordView.class)
    public String getPassword() {
        return this.password;
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        //创建对象
        User user = new User("isea533","123456");
        //序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        objectMapper.writerWithView(User.WithoutPasswordView.class).writeValue(bos, user);
        System.out.println(bos.toString());

        bos.reset();
        objectMapper.writerWithView(User.WithPasswordView.class).writeValue(bos, user);
        System.out.println(bos.toString());
    }
}

输出结果

{"username":"isea533"}
{"username":"isea533","password":"123456"}
        
	
		com.fasterxml.jackson.core
		jackson-core
		${jackson.version}
	

	
		com.fasterxml.jackson.core
		jackson-databind
		${jackson.version}
	

@EnableWebMvc在做什么?


如红框所示,在构建beanmap的列表过程中,会主动加载该类,构建默认bean列表。在DelegatingWebMvcConfiguration中,会建立以下默认bean列表。
HandlerMapping:
Bean: requestMappingHandlerMapping
Bean: viewControllerHandlerMapping
Bean: beanNameHandlerMapping
Bean: resourceHandlerMapping
Bean: defaultServletHandlerMapping
HandlerAdapter:
Bean: requestMappingHandlerAdapter
Bean: httpRequestHandlerAdapter
Bean: simpleControllerHandlerAdapter
ExceptionResolver
Bean: handlerExceptionResolver
Other:
Bean: mvcConversionService
Bean: mvcValidator
以上bean也是可以通过基于WebMvcConfigurationSupport派生新配置类来进行高级的修改上述bean的配置。

@Configuration
@EnableWebMvc
//@ComponentScan(basePackages = "web.api.module", useDefaultFilters = false, includeFilters = {
//        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})
//})
@ComponentScan("web.api.module.*")
@Import({ SecurityConfig.class })
public class WebConfig extends WebMvcConfigurationSupport {
	
	private static final Logger logger = Logger.getLogger(WebConfig.class);

	public WebConfig(){

	}

	@Bean
	public ViewResolver viewResolver() {
		logger.info("ViewResolver");
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}

    @Bean
    public MessageSource messageSource() {
    	logger.info("MessageSource");
    	ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    	messageSource.setBasename("config.messages.messages");
    	
    	return messageSource;
    }

    @Bean
    public HandlerAdapter servletHandlerAdapter(){
    	logger.info("HandlerAdapter");
    	return new SimpleServletHandlerAdapter();
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor(){
    	logger.info("LocaleChangeInterceptor");
    	return new LocaleChangeInterceptor();
    }

    @Bean(name="localeResolver")
    public CookieLocaleResolver cookieLocaleResolver(){
    	logger.info("CookieLocaleResolver");
    	return new CookieLocaleResolver();
    }

	@Bean
	public CsrfIntercepter initializingCsrfInterceptor(){
		logger.info("CsrfIntercepter");
		return new CsrfIntercepter();
	}
    
    /**                                                          
    * 描述 : <注册自定义拦截器>. 
*

<使用方法说明>

* @return */ @Bean public LoginCheckInterceptor initializingInterceptor(){ logger.info("LoginCheckInterceptor"); return new LoginCheckInterceptor(); } /** * 描述 : .
*

<这个比较奇怪,理论上应该是不需要的>

* @return */ @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { logger.info("RequestMappingHandlerMapping"); return super.requestMappingHandlerMapping(); } @Override protected void addInterceptors(InterceptorRegistry registry) { // TODO Auto-generated method stub logger.info("addInterceptors start"); registry.addInterceptor(localeChangeInterceptor()); registry.addInterceptor(initializingInterceptor()); // registry.addInterceptor(initializingCsrfInterceptor()); logger.info("addInterceptors end"); } @Bean public HandlerMapping resourceHandlerMapping() { logger.info("HandlerMapping"); return super.resourceHandlerMapping(); } /** * 描述 : <资源访问处理器>.
*

<可以在jsp中使用/static/**的方式访问/WEB-INF/static/下的内容>

* @param registry */ @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { logger.info("addResourceHandlers"); registry.addResourceHandler("/static/**").addResourceLocations("/WEB-INF/static/"); } /** * 描述 : <异常处理器>.
*

<系统运行时遇到指定的异常将会跳转到指定的页面>

* @return */ @Bean(name="exceptionResolver") public ExceptionResolver simpleMappingExceptionResolver(){ logger.info("ExceptionResolver"); ExceptionResolver simpleMappingExceptionResolver= new ExceptionResolver(); simpleMappingExceptionResolver.setDefaultErrorView("common_error"); simpleMappingExceptionResolver.setExceptionAttribute("exception"); Properties properties = new Properties(); properties.setProperty("java.lang.RuntimeException", "common_error"); simpleMappingExceptionResolver.setExceptionMappings(properties); return simpleMappingExceptionResolver; } /** * 描述 : .
*

<这个比较奇怪,理论上应该是不需要的>

* @return */ @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { logger.info("RequestMappingHandlerAdapter"); return super.requestMappingHandlerAdapter(); } @Override protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() { logger.info("ConfigurableWebBindingInitializer"); ConfigurableWebBindingInitializer initializer = super.getConfigurableWebBindingInitializer(); return initializer; } }

Hibernate的Entity等同于YII的Model

每个Entity是数据表的一行记录。

public class Main {
    private static final SessionFactory ourSessionFactory;

    static {
        try {
            Configuration configuration = new Configuration();
            //"hibernate.cfg.xml"
            configuration.configure("hibernate.cfg.xml");
            ourSessionFactory = configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static Session getSession() throws HibernateException {
        return ourSessionFactory.openSession();
    }

    public static void main(final String[] args) throws Exception {
        final Session session = getSession();
        try {
            System.out.println("querying all the managed entities...");
            final Map metadataMap = session.getSessionFactory().getAllClassMetadata();
            for (Object key : metadataMap.keySet()) {
                final ClassMetadata classMetadata = (ClassMetadata) metadataMap.get(key);
                final String entityName = classMetadata.getEntityName();
                final Query query = session.createQuery("from " + entityName);
                System.out.println("executing: " + query.getQueryString());
                List list = query.list();
                //列表查询回来的所有记录,观察后续的list变量吧。
                for (Object o : list) {
                    System.out.println("  " + o);
                }
            }
        } finally {
            session.close();
        }
    }
}

CGLib代理模式

CGLib是采用字节码方式注入到程序中的,这种方式就像C++中的Detour库注入汇编代码,从而达到监控函数运行的效果。由于CGLib是采用继承的关系,故它不能代理final类。以下是测试代码。
CglibProxy.java

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

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {

    // private static CglibProxy proxy = new CglibProxy();
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        enhancer.setSuperclass(clazz);// 设置需要创建子类的类
        enhancer.setCallback(this);
        return enhancer.create();// 通过字节码技术动态创建子类实例
    }

    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2,
                            MethodProxy arg3) throws Throwable {
        Object result = arg3.invokeSuper(arg0, arg2);
        return result;
    }
}
public class UserServiceImpl{
    public void removeUser(int userId) {
        System.out.println("模拟删除用户:" + userId);
    }
    public void addUser(int userId) {
        // TODO Auto-generated method stub
    }
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        UserServiceImpl userService =(UserServiceImpl)proxy.getProxy(UserServiceImpl.class);
        userService.removeUser(7);
    }
}