创建自己的IOC和事务管理(上)

大家都知道,Spring中IOC贯穿了其整个框架,IOC已经是框架设计中必不可少的部分,就实现上来讲Spring采取了配置文件的形式来实现依赖的注射,很好的解决了应用程序与服务之间的耦合的问题,除此之外,Spring还对事务管理提供了很好的支持。今天我要说的不是Spring的IOC,也不是Spring的事务管理,而是我自己写的类似Spring的IOC和事务管理,IOC采用工厂模式和单例模式来实现,事务管理使用动态代理模式来实现,当然功能没有Spring的那么强大。

beans.xml文件将配置数据库的相关信息、哪些类的哪些方法需要使用事务以及用来创建bean,具体配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- 数据库的配置 -->
<config>
<db-info>
<driver-name>com.mysql.jdbc.Driver</driver-name>
<url>jdbc:mysql://localhost:3306/jdbctest</url>
<username>root</username>
<password>111</password>
</db-info>
</config>

<bean-service>
<bean id="userDao" class="com.lrh.dao.UserDaoImpl">
</bean>
</bean-service>

<bean-dao>
<bean id="userService" class="com.lrh.service.UserServiceImpl">
</bean>
</bean-dao>

<aop-config>
<aop-pointcut expression="com.lrh.service"/>
</aop-config>
<tx-advice>
<tx-attributes>
<tx-method name="add*"/>
<tx-method name="delete*"/>
<tx-method name="modify*"/>
<tx-method name="*"/>
</tx-attributes>
</tx-advice>

</beans>

用来封装数据库配置信息的类:
package com.lrh.utils;

/**
* 用来封装数据库的配置数据
* @author jenhui
*
*/
public class JdbcConfig {

private String driverName;

private String url;

private String userName;

private String password;

public String getDriverName() {
return driverName;
}

public void setDriverName(String driverName) {
this.driverName = driverName;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public String toString() {
return this.getClass().getName() + "{driverName:" + driverName + ", url:" + url + ", userName:" + userName + "}";
}

}

读取数据库配置信息的类:
package com.lrh.utils;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
* 读取数据库配置信息
* @author jenhui
*
*/
public class JdbcConfigReader {

private static JdbcConfigReader instance = null;

private JdbcConfig jdbcConfig = new JdbcConfig();

private JdbcConfigReader() {
SAXReader reader = new SAXReader();
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("beans.xml");
try {
Document doc = reader.read(in);

Element driverNameElt = (Element)doc.selectObject("/beans/config/db-info/driver-name");
Element urlElt = (Element)doc.selectObject("/beans/config/db-info/url");
Element userNameElt = (Element)doc.selectObject("/beans/config/db-info/username");
Element passwordElt = (Element)doc.selectObject("/beans/config/db-info/password");

jdbcConfig.setDriverName(driverNameElt.getStringValue());
jdbcConfig.setUrl(urlElt.getStringValue());
jdbcConfig.setUserName(userNameElt.getStringValue());
jdbcConfig.setPassword(passwordElt.getStringValue());

} catch (DocumentException e) {
e.printStackTrace();
}
}

public static synchronized JdbcConfigReader getInstance() {
if (instance == null) {
instance = new JdbcConfigReader();
}
return instance;
}

public JdbcConfig getJdbcConfig() {
return jdbcConfig;
}

}

数据库的连接管理类:
package com.lrh.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
* 数据库连接管理类
* @author jenhui
*
*/
public class ConnectionManager {

private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();

public static Connection getConnection() {
Connection conn = connectionHolder.get();
if (conn == null) {
try {
JdbcConfig jdbcConfig = JdbcConfigReader.getInstance().getJdbcConfig();
Class.forName(jdbcConfig.getDriverName());
conn = DriverManager.getConnection(jdbcConfig.getUrl(), jdbcConfig.getUserName(), jdbcConfig.getPassword());
connectionHolder.set(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();

} catch (SQLException e) {
e.printStackTrace();

}
}
return conn;
}

public static void closeConnection() {
Connection conn = connectionHolder.get();
if (conn != null) {
try {
conn.close();
connectionHolder.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
}


public static void beginTransaction(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
conn.setAutoCommit(false);
}
}
}catch(SQLException e) {}
}

public static void commitTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.commit();
}
}
}catch(SQLException e) {}
}

public static void rollbackTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.rollback();
}
}
}catch(SQLException e) {}
}

}

使用动态代理模式来对被代理的类进行管理,如果被代理的类跟配置文件的表达式匹配,则进行事务代理(开启事物,事务提交,事物回滚)。
package com.lrh.utils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Element;
/**
*
* @author jenhui
*
*/
public class ProxyHandler implements InvocationHandler {

private Object targetObject=null;

public Object createProxyInstance(Object targetObject){
this .targetObject=targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj=null;
Connection conn=null;
try{
conn=ConnectionManager.getConnection();
System.out.println(conn);
List methodsEle=BeansFactory.getInstance().getDocument().selectNodes("/beans/tx-advice/tx-attributes/tx-method");
for(Iterator iter=methodsEle.iterator();iter.hasNext();){
Element methodEle=(Element)iter.next();
String str=methodEle.attributeValue("name");

if(method.getName().startsWith(str.substring(0, str.length()-1)) && str.length()>1){
ConnectionManager.beginTransaction(conn);
}
}
obj= method.invoke(targetObject, args);
if(!conn.getAutoCommit()){
ConnectionManager.commitTransaction(conn);
}
}catch(Exception e){
e.printStackTrace();
ConnectionManager.rollbackTransaction(conn);
}finally{
ConnectionManager.closeConnection();
}
return obj;
}

}

所有类将通过读取xml文件来创建,使用工厂模式和单例模式,创建好的bean将放到工厂中,同一系列的bean由同一工厂管理,这样就很好地降低各层之间的耦合性。

package com.lrh.utils;

import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.lrh.dao.UserDao;

/**
* 创建bean的工厂类
* @author jenhui
*
*/
public class BeansFactory {

private static BeansFactory instance=null;
private Map daoMap=new HashMap();
private Map serviceMap =new HashMap();
private Document document=null;

private BeansFactory(){

try{
SAXReader reader=new SAXReader();
document=reader.read(new FileInputStream("D:/workspace/beans.xml"));

}catch(Exception e){
e.printStackTrace();
}
}
public synchronized static BeansFactory getInstance(){
if(instance==null){
instance= new BeansFactory();
}
return instance;
}

public Object getServiceObject(String beanId){
if(serviceMap.containsKey(beanId)){
return serviceMap.get(beanId);

}
Element serviceEle=(Element)document.selectSingleNode("//bean[@id=\""+beanId+"\"]");
String className=serviceEle.attributeValue("class");
Object obj=null;
try{
obj=Class.forName(className).newInstance();
Element aopEle=(Element)document.selectSingleNode("/beans/aop-config/aop-pointcut");
String expression=aopEle.attributeValue("expression");
String packName=className.substring(0, className.lastIndexOf("."));

if(expression.equals(packName)){
ProxyHandler proxyHandler=new ProxyHandler();
obj=proxyHandler.createProxyInstance(obj);
}

serviceMap.put(beanId, obj);
}catch(Exception e){
e.printStackTrace();
}
return obj;
}

public Object getDaoObject(String beanId){
if(daoMap.containsKey(beanId)){
return daoMap.get(beanId);
}
Element daoEle=(Element)document.selectSingleNode("//bean[@id=\""+beanId+"\"]");
String className=daoEle.attributeValue("class");
Object obj=null;
try{
//obj=Class.forName(className).newInstance();
obj=Class.forName(className).newInstance();
Element aopEle=(Element)document.selectSingleNode("/beans/aop-config/aop-pointcut");
String expression=aopEle.attributeValue("expression");
String packName=className.substring(0, className.lastIndexOf("."));
if(expression.equals(packName)){
ProxyHandler proxyHandler=new ProxyHandler();
obj=proxyHandler.createProxyInstance(obj);
}
daoMap.put(beanId, obj);
}catch(Exception e){
e.printStackTrace();
}
return obj;
}

public Document getDocument(){
return document;
}
}

下面将贴出各个类的代码
包 com.lrh.orm下的类:
User类:
package com.lrh.orm;
/**
* @author jenhui
*
*/
public class User {

private String id;

private String name;

private String password;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

}

包com.lrh.dao下的接口或类:
UserDao接口:
package com.lrh.dao;

import com.lrh.orm.User;

/**
* @author jenhui
*
*/
public interface UserDao {

public void addUser(User user);
}

实现UserDao接口的UserDaoImpl类:
package com.lrh.dao;

import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.lrh.orm.User;
import com.lrh.utils.ConnectionManager;
/**
* @author jenhui
*
*/
public class UserDaoImpl implements UserDao {
public void addUser(User user) {
System.out.println("this is UserDaoImpl.addUser()");
String sql="insert into user(Id,Name,Password) values(?,?,?)";
try {
PreparedStatement ps = ConnectionManager.getConnection().prepareStatement(sql);
ps.setString(1, user.getId());
ps.setString(2, user.getName());
ps.setString(3, user.getPassword());
ps.execute();
System.out.println(ConnectionManager.getConnection());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

包 com.lrh.service下的接口或类:
UserService接口:
package com.lrh.service;

import com.lrh.orm.User;
/**
* @author jenhui
*
*/
public interface UserService {

public void addUser(User user);

}

实现UserService接口的UserServiceImpl类:
package com.lrh.service;

import com.lrh.dao.UserDao;
import com.lrh.orm.User;
import com.lrh.utils.BeansFactory;
/**
* @author jenhui
*
*/
public class UserServiceImpl implements UserService {

private UserDao userDao=(UserDao)BeansFactory.getInstance().getDaoObject("userDao");

public void addUser(User user) {
userDao.addUser(user);
}

}

最后编写一个类来测试一下:
package com.lrh.web;

import com.lrh.orm.User;
import com.lrh.service.UserService;
import com.lrh.utils.BeansFactory;
/**
* @author jenhui
*
*/
public class Client {

public static void main(String[] args){
UserService userService=(UserService)BeansFactory.getInstance().getServiceObject("userService");
User user=new User();
user.setId("A00810");
user.setPassword("QQ1259111695");
user.setName("kelly");
userService.addUser(user);
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值