更新時間:2015年12月29日13時44分 來源:傳智播客Java培訓學院 瀏覽次數(shù):
public class User { private Integer uid; private String username; private String password; |
public interface UserDao { /** * 保存 * @param user */ public void save(User user); } |
public class UserDaoImpl implements UserDao { @Override public void save(User user) { //TODO 暫時只打印 System.out.println(user); } } |
public interface UserService { /** * 注冊 * @param user */ public void register(User user); } |
public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void register(User user) { this.userDao.save(user); } } |
<?xml version="1.0" encoding="UTF-8"?> <beans> <!-- dao --> <bean id="userDaoId" class="cn.itcast.demo.dao.impl.UserDaoImpl"></bean> <!-- service --> <bean id="userServiceId" class="cn.itcast.demo.service.impl.UserServiceImpl"> <property name="userDao" ref="userDaoId"></property> </bean> </beans> |
<!-- 確定xml位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- 配置監(jiān)聽器 --> <listener> <listener-class>cn.itcast.myspring.listener.ContextLoaderListener</listener-class> </listener> |
public class ContextLoaderListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { // 0 獲得ServletContext對象應用 ServletContext context = sce.getServletContext(); // 1 加載配置 String config = context.getInitParameter("contextConfigLocation"); if(config == null){ //默認配置文件位置 config= "applicationContext.xml"; } InputStream xmlIs = null; // 2 處理路徑不同情況 // * classpath:applicationContext.xml --> 表示 src/applicationContext.xml // * applicationContext.xml --> 表示 /WEB-INF/applicationContext.xml if (config.startsWith("classpath:")) { // 2.1 加載 類路徑 (classpath、src)下的xml xmlIs = ContextLoaderListener.class.getClassLoader().getResourceAsStream(config.substring("classpath:".length())); } else { //2.2 加載/WEB-INF/目錄下的資源 xmlIs = context.getResourceAsStream("/WEB-INF/" + config); } //2.3 配置文件必須存在,否則拋異常 if(xmlIs == null){ throw new RuntimeException("資源文件["+config+"]沒有找到"); } //TODO 3 解析配置 if (xmlIs != null) { System.out.println(xmlIs); } } @Override public void contextDestroyed(ServletContextEvent sce) { } } |
/** * 用于封裝 <property name="userDao" ref="userDaoId"></property> */ public class Property { //屬性名稱 private String name; //另一個bean引用名 private String ref; public Property(String name, String ref) { super(); this.name = name; this.ref = ref; } |
public class Bean { //bean名稱 private String beanId; //bean的實現(xiàn)類 private String beanClass; //取值:singleton 單例,prototype 原型(多例)【擴展】 private String beanType; //所有的property private Set<Property> propSet = new HashSet<Property>(); public Bean(String beanId, String beanClass) { super(); this.beanId = beanId; this.beanClass = beanClass; } |
public class BeanFactory { //////////////////工廠模式//////////////////////// private static BeanFactory factory = new BeanFactory(); private BeanFactory(){ } /** * 獲得工廠實例 * @author lt * @return */ public static BeanFactory getInstance() { return factory; } |
//////////////////緩存所有的Bean///////////////////////////////// //bean數(shù)據(jù)緩存集合 ,key:bean名稱 ,value:bean封裝對象 private static Map<String, Bean> beanData;// = new HashMap<String, String>(); static{ // 從配置文件中獲得相應的數(shù)據(jù) 1.properties 2.xml //beanData.put("userDao", "com.itheima.ebs.service.impl.BusinessServiceImpl"); } public static void setBeanData(Map<String, Bean> beanData) { BeanFactory.beanData = beanData; } |
//TODO 3 解析配置 if (xmlIs != null) { //3.1解析 Map<String, Bean> data = parserBeanXml(xmlIs); //3.2 將解析結果放置到工廠中 BeanFactory.setBeanData(data); } |
/** * 將數(shù)據(jù)解析成bean * @param xmlIs * @return */ public static Map<String, Bean> parserBeanXml(InputStream xmlIs) { try { //0提供緩沖區(qū)域 Map<String, Bean> data = new HashMap<String, Bean>(); //1解析文件,并獲得Document Document document = Jsoup.parse(xmlIs, "UTF-8", ""); //2 獲得所有的bean元素 Elements allBeanElement = document.getElementsByTag("bean"); //3遍歷 for (Element beanElement : allBeanElement) { //5 將解析的結果封裝到bean中 // 5.1 bean名稱 String beanId = beanElement.attr("id"); // 5.2 bean實現(xiàn)類 String beanClass = beanElement.attr("class"); // 5.3 封裝到Bean對象 Bean bean = new Bean(beanId,beanClass); // 6 獲得所有的子元素 property Elements allPropertyElement = beanElement.children(); for (Element propertyElement : allPropertyElement) { String propName = propertyElement.attr("name"); String propRef = propertyElement.attr("ref"); Property property = new Property(propName, propRef); // 6.1 將屬性追加到bean中 bean.getPropSet().add(property); } data.put(beanId, bean); } return data; } catch (Exception e) { throw new RuntimeException(e); } } |
////////////////獲得Bean實例/////////////////////////////////// public Object getBean(String beanId) { try { // 通過bean 的名稱獲得具體實現(xiàn)類 Bean bean = beanData.get(beanId); if(bean ==null) return null; String beanClass = bean.getBeanClass(); Class clazz = Class.forName(beanClass); Object beanObj = clazz.newInstance(); //DI 依賴注入,將在配置文件中設置的內容,通過bean的set方法設置到bean實例中 Set<Property> props = bean.getPropSet(); for (Property property : props) { String propName = property.getName(); String propRef = property.getRef(); //另一個javabean,需要重容器中獲得 Object propRefObj = getBean(propRef); //PropertyDescriptor pd = new PropertyDescriptor(propName, clazz); //pd.getWriteMethod().invoke(bean, propRefObj); BeanUtils.setProperty(beanObj, propName, propRefObj); } return beanObj; } catch (Exception e) { throw new RuntimeException(e); } } |
//測試 UserService userService = (UserService) BeanFactory.getInstance().getBean("userServiceId"); userService.register(null); |
public class JdbcUtils { private static ThreadLocal<Connection> local = new ThreadLocal<Connection>(); static{ try { //注冊驅動 Class.forName("com.mysql.jdbc.Driver"); } catch (Exception e) { throw new RuntimeException(e); } } /** * 獲得連接 * @return */ public static Connection getConnection(){ try { Connection conn = local.get(); if (conn == null) { conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2", "root", "1234"); local.set(conn); } return conn; } catch (Exception e) { throw new RuntimeException(e); } } /** * 提交事務 */ public static void commit() { Connection conn = getConnection(); DbUtils.commitAndCloseQuietly(conn); } /** * 回滾事務 */ public static void rollback() { Connection conn = getConnection(); DbUtils.rollbackAndCloseQuietly(conn); } } |
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Transactional { } |
public Object getBean(String beanId) { try { // 通過bean 的名稱獲得具體實現(xiàn)類 Bean bean = beanData.get(beanId); if(bean ==null) return null; String beanClass = bean.getBeanClass(); Class<?> clazz = Class.forName(beanClass); Object beanObj = clazz.newInstance(); //DI 依賴注入,將在配置文件中設置的內容,通過bean的set方法設置到bean實例中 Set<Property> props = bean.getPropSet(); for (Property property : props) { String propName = property.getName(); String propRef = property.getRef(); //另一個javabean,需要重容器中獲得 Object propRefObj = getBean(propRef); //PropertyDescriptor pd = new PropertyDescriptor(propName, clazz); //pd.getWriteMethod().invoke(bean, propRefObj); BeanUtils.setProperty(beanObj, propName, propRefObj); } //如果類上有注解返回代理對象 if(clazz.isAnnotationPresent(Transactional.class)){ final Object _beanObj = beanObj; return Proxy.newProxyInstance( clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { //開啟事務 JdbcUtils.getConnection().setAutoCommit(false); //執(zhí)行目標方法 Object obj = method.invoke(_beanObj, args); //提交事務 JdbcUtils.commit(); return obj; } catch (Exception e) { //回顧事務 JdbcUtils.rollback(); throw new RuntimeException(e); } } }); } return beanObj; } catch (Exception e) { throw new RuntimeException(e); } } |
create table account( id int primary key auto_increment, username varchar(50), money int ); insert into account(username,money) values('jack','10000'); insert into account(username,money) values('rose','10000'); |
public class AccountDaoImpl implements AccountDao { private QueryRunner runner; public void setRunner(QueryRunner runner) { this.runner = runner; } @Override public void out(String outer, Integer money) { try { Connection conn = JdbcUtils.getConnection(); runner.update(conn, "update account set money = money - ? where username = ?", money, outer); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void in(String inner, Integer money) { try { Connection conn = JdbcUtils.getConnection(); runner.update(conn, "update account set money = money + ? where username = ?", money,inner); } catch (Exception e) { throw new RuntimeException(e); } } } |
@Transactional public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void transfer(String outer, String inner, Integer money) { accountDao.out(outer, money); //斷電 // int i = 1/0; accountDao.in(inner, money); } } |
<!-- 創(chuàng)建queryRunner --> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner"></bean> <bean id="accountDao" class="cn.itcast.dao.impl.AccountDaoImpl"> <property name="runner" ref="runner"></property> </bean> <!-- service --> <bean id="accountService" class="cn.itcast.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> |
public class AccountServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AccountService accountService = (AccountService) BeanFactory.getInstance().getBean("accountService"); accountService.transfer("jack", "rose", 100); } |