Netty网络聊天室之使用spring管理各种组件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/littleschemer/article/details/76973941
Spring是web开发的宠儿,不管mvc框架选择structs还是SpringMVC,IOC容器都是选择Spring。Spring有两个主要的作用,一个是IOC(依赖注入),另一个是AOP(面向切面编程)。只要是java项目,就可以使用这个框架。
在这里,我不过多对Spring进行布道。说一下有没有使用Spring的编码习惯。若不采用Spring进行项目开发,我们每个类一般都是采用单例的模式,例如 UserService.getInstance();使用了Spring,就只需要在UserService加个注解就可以把它丢入spring容器(Spring默认创建对象就是使用单例模式)。如果其他模块需要调用UserService的接口,只需要从spring容器把它拿出来即可,非常方便。

对于没有接触Spring的童鞋,只需要知道Spring是一个巨大的对象容器。使用@Component,@Servoce,@Controller,@Repository可以把对象放入容器,使用@Resource,@Autowired可以从容器里取对象。

spring管理组件的配置方式

1. 项目里受spring管理的组件是非常多的,所以我们需要能让spring容器自动扫描所有组件,只需要在spring配置加上这一行就可以了

<context:component-scan base-package="com.kingston" />
2. 把组件交给spring容器管理,配置如下

@Repository
public interface UserDao 
3. 使用Spring容器里的对象,配置如下

@Component
public class LoginService {

	@Autowired
	private UserDao userDao;
}

需要特别注意的是,这里用Autowired注解从spring里拿对象,LoginService本身也必须受spring管理,否则就需要手动从spring获取bean。

缓存Spring容器本身引用

1. 不是所有对象都放在spring容器里的。若某个对象本身没有放入spring里,想要拿spring容器的组件,就只能从spring的容器上下文环境中获取。所以,有必要把这个spring容器上下文缓存起来。要获取spring容器,只需要类实现ApplicationContextAware这个接口即可。像这样

public class SpringContext implements ApplicationContextAware {
	/** spring容器上下文 */
	private static ApplicationContext applicationContext = null;
	/** 异步持久化服务 */
	private static AysncDbService aysncDbService;
	
	private static ChatService chatService;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		SpringContext.applicationContext = applicationContext;
	}
	
	public final static <T> T getBean(Class<T> clazz) {
		return applicationContext.getBean(clazz);
	}
	
	public final static <T> Collection<T> getBeansOfType(Class<T> clazz) {
		return applicationContext.getBeansOfType(clazz).values();
	}
	
	public final static <T> T getBean(String name, Class<T> requiredType) {
		return applicationContext.getBean(name, requiredType);
	}

	@Resource
	public void setAysncDbService(AysncDbService aysncDbService) {
		SpringContext.aysncDbService = aysncDbService;
	}
	
	public static AysncDbService getAysncDbService() {
		return aysncDbService;
	}
	
	@Resource
	public void setChatService(ChatService chatService) {
		SpringContext.chatService = chatService;
	}
	
	public final static ChatService getChatService() {
		return chatService;
	}
	
}
并把SpringContext配置成spring的组件

	<!-- 注册spring上下文环境 -->
	<bean id="context" class="com.kingston.base.SpringContext" />
2. 非spring管理的实例想要获取spring组件,就可以像这样子了
	AbstractPacket  packet = (AbstractPacket)msg;
	System.err.println("receive pact, content is " + packet.getClass().getSimpleName());
	if(packet.getPacketType() == PacketType.ReqUserLogin ){
		ReqUserLoginPacket loginPact = (ReqUserLoginPacket)packet;
		
		LoginService loginMgr = SpringContext.getBean(LoginService.class);
		loginMgr.validateLogin(context,loginPact.getUserId(), loginPact.getUserPwd());
		return ;
	}

spring与mybatics的结合

使用了spring之后,数据库连接的数据源,以及Mybatics的SqlSessionFactoryBean就统统在spring进行配置就可以了。

1. 使用mybatis-spring库(mybatics整合spring的工具库),可以直接让spring扫描所有mybatics的mapper配置

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="config/mybatis-config.xml" />
		<!-- 自动扫描所有mapper配置 -->
		<property name="mapperLocations"
			value="classpath:com/kingston/data/mybatis/*Mapper.xml" />
	</bean>
2. 使用 mybatis-spring库,可以自动扫描所有dao并注入到spring容器
	<!-- 自动扫描所有dao并注入到spring容器 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.kingston.data.dao" />
	</bean>

3. 这样一来,mybatics本身的配置就变得可有可无啦。不过,一些组件的别名申明还是可以放到mybatics的配置里

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!--别名申明 -->
	<typeAliases>
		<typeAlias type="com.kingston.data.model.User" alias="user" />
	</typeAliases>
	
</configuration>
UserMapper.xml配置里的 resultType="user" ,这里的 "user"就指向上面的完整类路径
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kingston.data.dao.UserDao">
	<select id="findById" parameterType="java.lang.Long"
		resultType="user">
		select * from user where userId=#{userId}
	</select>
	<insert id="addUser" parameterType="user">
		insert into user(userId,userName,authentication) 
			values(#{userId},#{userName},#{authentication})
	</insert>
	<update id="updateUser" parameterType="user">
		update user
		set
		userName=#{userName}
		where userId=#{userId}
	</update>
	<delete id="delUser" parameterType="java.lang.Long">
		delete from user
		where
		userId=#{userId}
	</delete>
</mapper>

Spring结合Groovy脚本实现热部署

Groovy是JVM上的一门脚本语言,当Spring遇上了Groovy,就会缔造完美的效果。当部分spring组件需要在程序运行过程中实现代码热部署,只需要用Groovy的类加载器加载。具体的操作可以看下点击打开链接 这篇文章。
在实际使用环境,我们把需要热更新的代码统一放到src/groovy目录下。需要注意的是,ides开发环境跟jar包生产环境获取groovy目录的spring组件的方式是不同的。
在ide环境,只要将src/groovy目录标记为代码根目录,spring容器启动的时候,就可以扫描到groovy目录下被spring注解标记的组件。
在生产环境,我们使用maven作为打包工具,但maven 默认只把src/main目录下的java文件编译到目标jar包,我们自定义的src/groovy目录是不会打进包里的。这样更好,因为我们本来就不希望我们的groovy目录被编译成class。
我们希望groovy的目录与jar包分离,并且以源码的形式存在。当需要更新groovy里某个文件的代码时,直接替换文件即可。GroovyFactory类在扫描的时候,只要把扫描的根目录指向跟jar包同一目录下的groovy,也可以拿到groovy的spring组件。


全部代码已在github上托管

服务端代码请移步 --> netty聊天室服务器

客户端代码请移步 --> netty聊天室客户端





猜你喜欢

转载自blog.csdn.net/littleschemer/article/details/76973941