java入门学习(九)

来源:互联网 发布:mysql数据库查询工具 编辑:程序博客网 时间:2024/05/20 22:03

到这步,在网上又看到了注解和扫描的方式,也试着处理一下。(下面的代码在以前的上面做了修改,主要是去掉了PK的泛型,改为Serializable了)

用最简单的context:component-scan方式,applicationContext.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"xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd  ">    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="oracle.jdbc.OracleDriver" /><property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" /><property name="username" value="MyBatis" /><property name="password" value="MyBatis" /></bean><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="configLocation" value="classpath:mybatis-configuration.xml" /></bean><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg index="0" ref="sqlSessionFactory" /></bean><context:component-scan base-package="mybatistest"/></beans>

首先要注意加入,xmlns:context="http://www.springframework.org/schema/context,然后配置一个最简单的<context:component-scan base-package="mybatistest"/>,以前的这块的bean配置就可以删除。

试了一下,这时还不会起效,需要对bean做注解,先试着将UserDaoImpl改为自动注册方式:

package mybatistest.dao.impl;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Repository;import mybatistest.dao.UserDao;import mybatistest.entity.User;@Repository@Scope("prototype")   public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {public String getUserString(String id) {return "UserDao.getUserString";}}

Test.java先改来测试一下看是否有注册起

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");//打印自动注册的类for (String beanName:ac.getBeanDefinitionNames()){System.out.println(beanName);

运行,结果报错:Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required,也就是说从SqlSessionDaoSupport继承的子类,没有自动注入'sqlSessionFactory' or 'sqlSessionTemplate'。点开看一下SqlSessionDaoSupport源码,确实没有看到有注解。然后看到源码中有句注释: * {code Autowired} was removed from setSqlSessionTemplate and setSqlSessionFactory
 * in version 1.2.0.

看来需要自己处理了。还好,前面有个父类BaseDaoImpl,这样就可以只改父类,子类就全都可以自动注入了(程序也要拼爹啊),BaseDaoImpl.java

package mybatistest.dao.impl;import java.io.Serializable;import java.lang.reflect.ParameterizedType;import org.mybatis.spring.SqlSessionTemplate;import org.mybatis.spring.support.SqlSessionDaoSupport;import org.springframework.beans.factory.annotation.Autowired;import mybatistest.dao.BaseDao;public class BaseDaoImpl<T> extendsSqlSessionDaoSupport implements BaseDao<T> {private Class<T> clazz;@SuppressWarnings("unchecked")public BaseDaoImpl() {this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];}public T getByID(Serializable id) {String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();return getSqlSession().selectOne(clazz.getName() + "." + methodName, id);}//SqlSessionDaoSupport没有提供注解注入@Autowired  public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {    super.setSqlSessionTemplate(sqlSessionTemplate);  }}

覆写一下SqlSessionDaoSupport类的setSqlSessionTemplate,将其注解设置为@Autowired

运行一下,可以看到UserDaoImpl对应的Bean已注册了:(名称为userDaoImpl,第1个字母是小写的)

dataSource
transactionManager
sqlSessionFactory
sqlSession
userDaoImpl
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor

再来对Service层做注解(为处理第七章的子类强制转换,又考虑了一下,采用泛型处理,重新定义了一个D,代表DAO的泛型,重新研究还花了点时间才自己感觉OK了),先看父接口BaseService.java:

package mybatistest.service;import java.io.Serializable;import mybatistest.dao.BaseDao;public interface BaseService<T> {public T getByID(Serializable id);}

UserService.java

package mybatistest.service;import mybatistest.dao.UserDao;import mybatistest.entity.User;public interface UserService extends BaseService<User>{public String userLogin(String userNumber, String userPassword);  }

BaseServiceImpl.java,这个父类改造还花了点时间:

package mybatistest.service.impl;import java.io.Serializable;import org.springframework.beans.factory.annotation.Autowired;import mybatistest.dao.BaseDao;import mybatistest.service.BaseService;public abstract class BaseServiceImpl<T,  D extends BaseDao<T>> implementsBaseService<T> {@Autowiredprivate D mainDao;//供子类使用protected D getMainDao() {return mainDao;}public T getByID(Serializable id) {return mainDao.getByID(id);};}这里要注意一下:
 @Autowired private D mainDao;
这样各个子类都可以自动注入一个“主刀”。比如UserServiceImpl对应到UserDaoImpl。同时,子类也解决了第七章中的强制转换,比如子类UserServiceImpl就不用强制转换就可以使用UserDao中定义的未在BaseDao中定义的方法,java泛型真的强。
再来,UserServiceImpl.java
package mybatistest.service.impl;import org.springframework.stereotype.Service;import mybatistest.dao.UserDao;import mybatistest.entity.User;import mybatistest.service.UserService;@Servicepublic class UserServiceImpl extends BaseServiceImpl<User, UserDao> implementsUserService {public String userLogin(String userNumber, String userPassword) {//((UserDao) mainDao).getUserString("");//子类可以不用强制转换了//getMainDao().getUserString("1");User user = getMainDao().getByID("1");if (null == user) {return "用户不存在!";}if ("XXX" != userPassword) {return "密码不正确!";}return "登录成功!";}}


OK,再运行Test看看:

dataSource
transactionManager
sqlSessionFactory
sqlSession
userDaoImpl
userServiceImpl
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
可以看到,userDaoImpl、userServiceImpl都已注册上了。再改一下Test.java:

package mybatistest;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import mybatistest.entity.User;import mybatistest.service.UserService;import mybatistest.service.impl.UserServiceImpl;public class Test {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");//打印自动注册的类//for (String beanName:ac.getBeanDefinitionNames()){//System.out.println(beanName);//}// 注意定义成接口,并通过getBean方式取得Bean//UserService userService = (UserService) ac.getBean("userServiceImpl");UserService userService = ac.getBean(UserServiceImpl.class);// 测试从接口中的服务取一个entityUser user = userService.getByID("1");System.out.println(user.getUserName());// 测试调接口的userLogin服务System.out.println(userService.userLogin("1", "XXX"));}}


再运行,结果出来了:

张三
登录成功!

 

这里又要思考了,用这种注解的方式,虽然xml文件配置简化了,便感觉还是有缺点:

1、没有xml中手工定义Bean和对应的注入那样,各种引用关系之间很清晰;

2、相当于是xml中移到了代码中,有问题就要从代码中改再编译发布;

3、换一套实现类时,要麻烦些(应该也可以从context:component-scan的base-package及两个子标签来处理吧)
大概也就是鱼与熊掌不能兼得吧。


 


 

0 0