国产色诱美女免费视频|欧美精彩狠狠色丁香婷婷|91黑人|日本黄色小视频|欧美一级黄色视频在这里免费观看

IT培訓(xùn)-高端面授IT培訓(xùn)機(jī)構(gòu)
云和教育:云和數(shù)據(jù)集團(tuán)高端IT職業(yè)教育品牌
  • 國(guó)家級(jí)
    全民數(shù)字素養(yǎng)與技能培訓(xùn)基地
  • 河南省
    第一批產(chǎn)教融合型企業(yè)建設(shè)培育單位
  • 鄭州市
    數(shù)字技能人才(碼農(nóng))培養(yǎng)評(píng)價(jià)聯(lián)盟

鄭州java培訓(xùn)教程:自定義spring

  • 發(fā)布時(shí)間:
    2016-10-12
  • 版權(quán)所有:
    云和教育
  • 分享:

鄭州java培訓(xùn)教程:自定義spring

1 Java培訓(xùn)實(shí)戰(zhàn)教程之自定義spring

1.1 描述

在企業(yè)級(jí)開發(fā)中,spring框架應(yīng)用非常廣。為了讓已經(jīng)學(xué)習(xí)過(guò)spring框架同學(xué),可以更深入的理解和應(yīng)用spring,本文將通過(guò)自定義spring,更佳系統(tǒng)的闡述spring核心:IoC、AOP。

IoC(Inversion of Control)控制反轉(zhuǎn):將對(duì)象的創(chuàng)建權(quán)交與spring框架,及將創(chuàng)建權(quán)反轉(zhuǎn)給spring框架。IoC主要解決計(jì)算機(jī)程序的耦合問(wèn)題。

AOP(Aspect Oriented Programming)面向切面編程:通過(guò)運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。

1.2 分析

如果要實(shí)現(xiàn)自定義spring,可以將器拆分成多個(gè)功能實(shí)現(xiàn)。

階段一:編寫配置文件,服務(wù)器tomcat啟動(dòng)時(shí),加載配置文件

階段二:使用Jsoup解析xml,并封裝到指定的JavaBean中

階段三:編寫工廠類用于創(chuàng)建指定bean,并完成property注入

階段四:使用@Transactional進(jìn)行事務(wù)管理

1.3 搭建環(huán)境

1.3.1 javabean

public?class?User {

private?Integer uid;

private?String username;

private?String password;

1.3.2?? ?dao

public?interface?UserDao {

/**

* 保存

*?@param?user

*/

public?void?save(User user);}

public?class?UserDaoImpl?implements?UserDao {

@Override

public?void?save(User user) {

//TODO?暫時(shí)只打印

System.out.println(user);

}

}

1.3.3?? service

public?interface?UserService {

/**

* 注冊(cè)

*?@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);

}

}

1.4?? 階段一:編寫配置文件,服務(wù)器啟動(dòng)加載

1.4.1?? xml配置文件

l? 在src下添加“applicationContext.xml”,并將dao和service配置到xml文件中。

l? 使用<bean>標(biāo)簽配置一個(gè)實(shí)現(xiàn)類

class:??? 配置實(shí)現(xiàn)類的全限定名稱

id: 進(jìn)行唯一命名,用于提供給程序獲得

l? 使用<property>配置javabean屬性的注入

name:?? 配置的service的屬性名

ref:?????? 配置其他bean對(duì)象的引用

<?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>

1.4.2?? 加載配置文件

l? tomcat啟動(dòng)時(shí),加載配置文件方式總結(jié):

1.編寫Servlet,配置servlet,并添加<load-on-startup>,在init(ServletConfig)初始化方式中加載。

2.編寫Filter,配置filter,在init(FilterConfig)初始化方法中加載

3.編寫Listener,實(shí)現(xiàn)接口ServletContext,配置listener,在contextInitialized(ServletContextEvent sce)方法中加載。

l? spring采用listener方案

1.提供實(shí)現(xiàn)類ContextLoaderListener

2.編寫全局初始化參數(shù)contextConfigLocation,用于確定xml位置

<param-value>classpath:applicationContext.xml</param-value> 加載類路徑下的xml文件

<param-value>applicationContext.xml</param-value> 加載WEB-INF目錄的配置文件

l? xml配置

<!– 確定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>

l? 實(shí)現(xiàn)類

1.4.2?? 加載配置文件

l? tomcat啟動(dòng)時(shí),加載配置文件方式總結(jié):

1.編寫Servlet,配置servlet,并添加<load-on-startup>,在init(ServletConfig)初始化方式中加載。

2.編寫Filter,配置filter,在init(FilterConfig)初始化方法中加載

3.編寫Listener,實(shí)現(xiàn)接口ServletContext,配置listener,在contextInitialized(ServletContextEvent sce)方法中加載。

l? spring采用listener方案

1.提供實(shí)現(xiàn)類ContextLoaderListener

2.編寫全局初始化參數(shù)contextConfigLocation,用于確定xml位置

<param-value>classpath:applicationContext.xml</param-value> 加載類路徑下的xml文件

<param-value>applicationContext.xml</param-value> 加載WEB-INF目錄的配置文件

l? xml配置

<!– 確定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>

l? 實(shí)現(xiàn)類

public?class?ContextLoaderListener?implements?ServletContextListener {

@Override

public?void?contextInitialized(ServletContextEvent sce) {

// 0 獲得ServletContext對(duì)象應(yīng)用

ServletContext context = sce.getServletContext();

// 1 加載配置

String config = context.getInitParameter(“contextConfigLocation”);

if(config ==?null){ //默認(rèn)配置文件位置

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) {

}

}

1.5?? 階段二:解析xml,并封裝到指定javabean中

1.提供Property類,用于封裝<property name=” ”?ref=” “></property>

2.提供Bean類,用于封裝<bean id=” ”?class=” “>

一個(gè)<bean> 標(biāo)簽體中可以配置多個(gè)<property>需要一個(gè)容器存放,沒有順序要求,且不能重復(fù),選擇Set

3.提供BeanFactory類,并在類同提供容器存放多個(gè)Bean 類,為了方便獲取使用Map。

1.5?? 階段二:解析xml,并封裝到指定javabean中

1.提供Property類,用于封裝<property name=” ”?ref=” “></property>

2.提供Bean類,用于封裝<bean id=” ”?class=” “>

一個(gè)<bean> 標(biāo)簽體中可以配置多個(gè)<property>需要一個(gè)容器存放,沒有順序要求,且不能重復(fù),選擇Set

3.提供BeanFactory類,并在類同提供容器存放多個(gè)Bean 類,為了方便獲取使用Map。

1.5.1?? ?property javabean

/**

* 用于封裝 <property name=”userDao”?ref=”userDaoId”></property>

*/

public?class?Property {//屬性名稱

private?String name;

//另一個(gè)bean引用名

private?String ref;

public?Property(String name, String ref) {

super();

this.name = name;

this.ref = ref;

}

1.5.2?? ?bean? javabean

public?class?Bean {

//bean名稱

private?String beanId;

//bean的實(shí)現(xiàn)類

private?String beanClass;

//取值:singleton 單例,prototype 原型(多例)【擴(kuò)展】

private?String beanType;

//所有的property

private?Set<Property> propSet =?new?HashSet<Property>();

public?Bean(String beanId, String beanClass) {

super();

this.beanId =?beanId;

this.beanClass = beanClass;

}

1.5.3?? ?BeanFactory 工廠模式類

public?class?BeanFactory {

//////////////////工廠模式////////////////////////

private?static?BeanFactory?factory?=?new?BeanFactory();

private?BeanFactory(){

}

/**

* 獲得工廠實(shí)例

*?@author?lt

*?@return

*/

public?static?BeanFactory getInstance() {

return?factory;

}

1.5.4?? ?BeanFactory 提供Map 緩存

//////////////////緩存所有的Bean/////////////////////////////////

//bean數(shù)據(jù)緩存集合 ,key:bean名稱 ,value:bean封裝對(duì)象

private?static?Map<String, Bean>?beanData;// = new HashMap<String, String>();

static{

// 從配置文件中獲得相應(yīng)的數(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;

}

1.5.5?? ?修改Listener解析xml

l? 使用Jsoup解析,導(dǎo)入jar包

l? 修改contextInitialized 方法

//TODO?3 解析配置

if?(xmlIs !=?null) {

//3.1解析

Map<String, Bean> data =?parserBeanXml(xmlIs);

//3.2 將解析結(jié)果放置到工廠中

BeanFactory.setBeanData(data);

}

l? 解析方法parserBeanXml(InputStream)

/**

* 將數(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 將解析的結(jié)果封裝到bean中

// 5.1 bean名稱

String beanId = beanElement.attr(“id”);

// 5.2 bean實(shí)現(xiàn)類

String beanClass = beanElement.attr(“class”);

// 5.3 封裝到Bean對(duì)象

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);

}

}

1.6?? 階段三:完善BeanFactory獲得實(shí)例

l? 使用 BeanUtils.setProperty 設(shè)置數(shù)據(jù),需要導(dǎo)入jar包

l? BeanFactory 提供 getBean方法

////////////////獲得Bean實(shí)例///////////////////////////////////

public?Object getBean(String beanId) {try?{

// 通過(guò)bean 的名稱獲得具體實(shí)現(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 依賴注入,將在配置文件中設(shè)置的內(nèi)容,通過(guò)bean的set方法設(shè)置到bean實(shí)例中

Set<Property> props = bean.getPropSet();

for?(Property property : props) {

String propName = property.getName();

String propRef = property.getRef(); //另一個(gè)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);

}

}

l? 測(cè)試

//測(cè)試

UserService userService = (UserService) BeanFactory.getInstance().getBean(“userServiceId”);

userService.register(null);

1.7?? 階段四:spring事務(wù)管理

1.7.1?? 修改自定義spring

l? 提供JdbcUtils工具類,用于在當(dāng)前線程中共享Connection

l? 提供@Transaction 用于標(biāo)記那些類需要進(jìn)行事務(wù)管理

1.7.1.1???????? JdbcUtils工具類

l? 使用ThreadLocal 保存Connection,在當(dāng)前線程中共享Connection

l? 并提供提交和回滾方法,自動(dòng)關(guān)閉連接

public?class?JdbcUtils {

private?static?ThreadLocal<Connection>?local?=?new?ThreadLocal<Connection>();

static{

try?{

//注冊(cè)驅(qū)動(dòng)

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);

}

}

/**

* 提交事務(wù)

*/

public?static?void?commit() {

Connection conn =?getConnection();

DbUtils.commitAndCloseQuietly(conn);

}

/**

* 回滾事務(wù)

*/

public?static?void?rollback() {

Connection conn =?getConnection();

DbUtils.rollbackAndCloseQuietly(conn);

}

}

1.7.1.2???????? @Transactional

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public?@interface?Transactional {}

1.7.1.3???????? 修改BeanFactory

l? 通過(guò)getBean 獲得對(duì)象實(shí)例時(shí),如果對(duì)象有@Transactional注解,將返回代理對(duì)象,對(duì)目標(biāo)對(duì)象上所有的方法都進(jìn)行事務(wù)管理。

l? 如果沒有異常提交事務(wù),并關(guān)閉連接

l? 如果有異常回滾事務(wù),并關(guān)閉連接

public?Object getBean(String beanId) {

try?{

// 通過(guò)bean 的名稱獲得具體實(shí)現(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 依賴注入,將在配置文件中設(shè)置的內(nèi)容,通過(guò)bean的set方法設(shè)置到bean實(shí)例中

Set<Property> props = bean.getPropSet();

for?(Property property : props) {

String propName = property.getName();

String propRef = property.getRef(); //另一個(gè)javabean,需要重容器中獲得

Object propRefObj = getBean(propRef);

//PropertyDescriptor?pd?= new PropertyDescriptor(propName,?clazz);

//pd.getWriteMethod().invoke(bean, propRefObj);

BeanUtils.setProperty(beanObj, propName, propRefObj);

}

//如果類上有注解返回代理對(duì)象

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?{

//開啟事務(wù)

JdbcUtils.getConnection().setAutoCommit(false);

//執(zhí)行目標(biāo)方法

Object obj = method.invoke(_beanObj, args);

//提交事務(wù)

JdbcUtils.commit();

return?obj;

}?catch?(Exception e) {

//回顧事務(wù)

JdbcUtils.rollback();

throw?new?RuntimeException(e);

}

}

});

}

return?beanObj;

}?catch?(Exception e) {

throw?new?RuntimeException(e);

}

}

1.7.2?? 初始化數(shù)據(jù)庫(kù)

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′);

1.7.3?? dao層

l? 必須使用自定義spring提供的JdbcUtils獲得連接,從而保證當(dāng)前線程使用的是同一個(gè)線程。

l? 通過(guò)xml配置文件創(chuàng)建QueryRunner實(shí)例,并注入給dao

l? 擴(kuò)展:如果將QueryRunner和JdbcUtils都省略,需要自己實(shí)現(xiàn)JdbcTemplate完成。

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);

}

}

}

1.7.4?? service層

l? 在實(shí)現(xiàn)類上添加注解

@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);

}

}

1.7.5?? 編寫spring配置

<!– 創(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>

1.7.6?? 編寫servlet測(cè)試

l? 通過(guò)請(qǐng)求servlet,進(jìn)行轉(zhuǎn)賬,此處使用固定值進(jìn)行測(cè)試

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);

}