??xml version="1.0" encoding="utf-8" standalone="yes"?> 我们的思\是先写一个BaseDaoQ仿照HibernateTemplateQ将基本功能全部实现Q?/p>
public class BaseDao extends HibernateDaoSupport{ private Log log = LogFactory.getLog(getClass()); public Session openSession() { public Object get(Class entityClass, Serializable id) throws DataAccessException { public Serializable create(Object entity) throws DataAccessException { ... 其它的DAOQ从BaseDaol承出来Q这样写其他的DAOQ代码就会很?/p>
从BaseDaol承出来EntityDaoQ专门负责一般实体的基本操作Q会更方ѝ?/p>
public interface EntityDao { public Object get(Class entityClass, Serializable id) throws DataAccessException; public Object load(Class entityClass, Serializable id) throws DataAccessException; public Serializable create(Object entity) throws DataAccessException; /** } ZTransaction的控Ӟ采用AOP的方式: public interface EntityManager { public Object get(Class entityClass, Serializable id); public Object load(Class entityClass, Serializable id); public Serializable create(Object entity); } /** private EntityDao entityDao; public void setEntityDao(EntityDao entityDao) { public Object get(Class entityClass, Serializable id) { public Object load(Class entityClass, Serializable id) { } q样我们有了一个通用的Hibernate实体引擎Q可以对MHibernate实体实现基本的增加、修攏V删除、查询等?/p>
其它的BusinessService可以承EntityManagerQ快速实C务逻辑?/p>
具体XML配置如下Q?/p>
<!-- Oracle JNDI DataSource for J2EE environments --> <!-- Hibernate SessionFactory for Oracle --> <!-- AOP DAO Intecepter --> <bean id="entityDaoTarget" class="com.gpower.services.entity.dao.EntityDaoImpl"> <bean id="entityDao" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> <!-- Transaction manager that delegates to JTA (for a transactional JNDI DataSource) --> <!-- Transactional proxy for the Application primary business object --> <bean id="entityManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
Spring支持从数据动态生成PDF或Excel文g
下面q个单实现的例子实现了spring输出PDF和Excel文gQؓ了用Excel电子表格Q你需要在你的classpath中加入poi-2.5.1.jar库文Ӟ而对PDF文gQ则需要iText.jar文g。它们都包含在Spring的主发布包中?br />
下面是测试项目代码:
1、控制器配置代码<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="beanNameViewResolver"
class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean id="viewController" class="com.zhupan.spring.ViewController" />
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/view*.shtml">viewController</prop>
</props>
</property>
</bean>
</beans>
3、用于Excel视图的视囑֭cd
Z在生成输出文档的q程中实现定制的行ؓQ我们将l承合适的抽象cR对于ExcelQ这包括提供一?org.springframework.web.servlet.view.document.AbstractExcelView的子c,q实?buildExcelDocumentҎ?br />package com.zhupan.view;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.servlet.view.document.AbstractExcelView;
public class ViewExcel extends AbstractExcelView
{
public void buildExcelDocument(
Map model, HSSFWorkbook workbook,
HttpServletRequest request, HttpServletResponse response)
throws Exception
{
HSSFSheet sheet = workbook.createSheet("list");
sheet.setDefaultColumnWidth((short) 12);
HSSFCell cell = getCell(sheet, 0, 0);
setText(cell, "Spring Excel test");
HSSFCellStyle dateStyle = workbook.createCellStyle();
dateStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy"));
cell = getCell(sheet, 1, 0);
cell.setCellValue(new Date());
cell.setCellStyle(dateStyle);
getCell(sheet, 2, 0).setCellValue(458);
HSSFRow sheetRow = sheet.createRow(3);
for (short i = 0; i < 10; i++)
{
sheetRow.createCell(i).setCellValue(i * 10);
}
}
}
4、用于PDF视图的视囑֭cd
需要象下面一L承org.springframework.web.servlet.view.document.AbstractPdfViewQƈ实现buildPdfDocument()Ҏ?package com.zhupan.view;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.view.document.AbstractPdfView;
import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;
public class ViewPDF extends AbstractPdfView
{
public void buildPdfDocument(Map model, Document document,
PdfWriter writer, HttpServletRequest request,
HttpServletResponse response) throws Exception
{
List list = (List) model.get("list");
for (int i = 0; i < list.size(); i++)
document.add(new Paragraph((String) list.get(i)));
}
}
package com.zhupan.spring;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import com.zhupan.view.ViewExcel;
import com.zhupan.view.ViewPDF;
public class ViewController extends MultiActionController
{
public ModelAndView viewPDF(HttpServletRequest request, HttpServletResponse response) throws Exception
{
List list = new ArrayList();
Map model=new HashMap();
list.add("test1");
list.add("test2");
model.put("list",list);
ViewPDF viewPDF=new ViewPDF();
return new ModelAndView(viewPDF,model);
}
public ModelAndView viewExcel(HttpServletRequest request, HttpServletResponse response) throws Exception
{
List list = new ArrayList();
Map model=new HashMap();
list.add("test1");
list.add("test2");
model.put("list",list);
ViewExcel viewExcel=new ViewExcel();
return new ModelAndView(viewExcel,model);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>springPDFTest</display-name>
<servlet>
<servlet-name>springPDFTest</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springPDFTest</servlet-name>
<url-pattern>*.shtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
3)index.jsp<%
@ page contentType="text/html; charset=gb2312"%>
<a href="viewPDF.shtml">PDF视图打开 </a>
<br>
<a href="viewExcel.shtml">Excel视图打开</a>
]]>
Spring Framework最得以出名的是与Hibernate的无~链接,基本上用SpringQ就会用Hibernate。可惜的是Spring提供的HibernateTemplate功能昑־不够Q用v来也不是很方ѝ我们编E序Ӟ一般先写BusinessServiceQ由BusinessService调DAO来执行存储,在这斚wSpring没有很好的例子,造成真正想用好它Qƈ不容易?/p>
return SessionFactoryUtils.getSession(getSessionFactory(), false);
}
Session session = openSession();
try {
return session.get(entityClass, id);
}
catch (HibernateException ex) {
throw SessionFactoryUtils.convertHibernateAccessException(ex);
}
}
Session session = openSession();
try {
return session.save(entity);
}
catch (HibernateException ex) {
throw SessionFactoryUtils.convertHibernateAccessException(ex);
}
}
...}
* Base class for Hibernate DAOs. This class defines common CRUD methods for
* child classes to inherit. User Sping AOP Inteceptor
*/
public class EntityDaoImpl extends BaseDao implements EntityDao{
...
* Base class for Entity Service. User Sping AOP Inteceptor
*/
public class EntityManagerImpl implements EntityManager {
this.entityDao = entityDao;
}
return entityDao.get(entityClass, id);
}
return entityDao.load(entityClass, id);
}
...
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>java:comp/env/jdbc/testPool</value></property>
</bean>
<!-- Choose the dialect that matches your "dataSource" definition -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<value>user-hbm.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.Provider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<property name="proxyInterfaces">
<value>com.gpower.services.entity.dao.EntityDao</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
<value>entityDaoTarget</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
<!--
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
-->
<bean id="entityManagerTarget" class="com.gpower.services.entity.EntityManagerImpl">
<property name="entityDao">
<ref bean="entityDao"/>
</property>
</bean>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="target">
<ref bean="entityManagerTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_SUPPORTS</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
]]>
Spring Framework从诞生之日vQ受C来多的关注。最q,新的开源项目大多支持Spring Framework。国内目前也有专门的|站Q?a >http://spring.jactiongroup.net/Q。那它ؓ什么如此受Ƣ迎呢?
我想最重要的是QEJB让每个h都痛恨。要~写一个EJBQ需要写LocalHome, RemoteHome, Bean, LocalInterface, RemoteInterfaceQ需要一个标准描q符Q一个特D厂商描q符QWeblogic、WebSphere都不一PQ如果是Entity BeanQ还需要Mapping文g。如此之多,实在ȝ。但EJB最重要的是解决Transaction问题Q没有Spring之前Q没有其他方法能够描q式的解军_。每个h、每个公ؓ了解决Transaction的问题,~程的写法都不一P百花齐放。于是,在最需要它的时候,Spring出现了?/p>
Spring的功能非常多。但对于一个品,最重要的是如何用好它的_֍。Spring包含AOP、ORM、DAO、Context、Web、MVC几个部分l成。Web、MVC暂不用考虑Q用成熟的Struts、JSP或Webwork更好。DAO׃目前Hibernate、JDO的流行,也可不考虑。因此最需要用的是AOP、ORM、Context?/p>
Context中,最重要的是BeanfactoryQ它是将接口与实现分开Q非帔R要。以前我们写E序Q如一个接口IDocumentQ一个实现类Document1。在写程序时Q需写成IDocument doc = new Document1()Q一旦我们的实现c需改变Ӟ变ؓDocument2Q则E序需写成IDocument doc = new Document2()Q所有用到的地方全需攏VBeanfactory帮我们解决了q个问题Q用context后,写法变ؓIDocument doc=(IDocument)beanFactory.getBean("doc")。如果实现类从Document1改ؓDocument2Q直接在配置文g改就可以了。Context是Bean factory的进一步抽象。很多h都喜Ƣ用ApplicationConextQ用Servlet把它Load。这样就把Bean Factory与Webl定在一赗如果是Fat Client或Remote调用Q则q些Bean factory很难调用,实际是将表现层与业务层绑定的太紧。推荐的Ҏ是SingletonBeanFactoryLocator。具体ؓQ?/p>
BeanFactoryLocator bfLocator = SingletonBeanFactoryLocator.getInstance();
BeanFactoryReference bf = bfLocator.useBeanFactory("beanFactory");
// now use some bean from factory
return bf.getFactory().getBean(name);
<beans>
<bean id="beanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>dataAccessContext.xml</value>
<value>securityContext.xml</value>
<value>...</value>
</list>
</constructor-arg>
</bean>
</beans>
q样Q就可随时动态扩展,实现lg式的开发?/p>
Q未完,待箋Q?/p>
增加以下内容
UserDAO.java
public interface UserDAO {
public abstract boolean isValidUser(String username, String password);
}
UserDAOImp.java
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.test.Hibernate.SessionFactory;
public class UserDAOImp extends HibernateDaoSupport implements UserDAO {
private SessionFactory sessionFactory;
private static String hql = "from User u where u.username=? ";
public boolean isValidUser(String username, String password) {
List userList = this.getHibernateTemplate().find(hql, username);
if (userList.size() > 0) {
return true;
}
return false;
}
}
Aspect Oriented Programming(AOP)Q面向切面编E,是一个比较热门的话题。AOP主要实现的目的是针对业务处理q程中的切面q行提取Q它所面对的是处理q程中的某个步骤或阶D,以获得逻辑q程中各部分之间低耦合性的隔离效果。比如我们最常见的就是日志记录了QD个例子,我们现在提供一个服务查询学生信息的Q但是我们希望记录有谁进行了q个查询。如果按照传l的OOP的实现的话,那我们实C一个查询学生信息的服务接口(StudentInfoService)和其实现c(StudentInfoServiceImpl.javaQ,同时Z要进行记录的话,那我们在实现c?StudentInfoServiceImpl.java)中要d其实现记录的q程。这L话,假如我们要实现的服务有多个呢Q那p在每个实现的c都dq些记录q程。这样做的话׃有点J琐Q而且每个实现c都与记录服务日志的行ؓ紧耦合Q违反了面向对象的规则。那么怎样才能把记录服务的行ؓ与业务处理过E中分离出来呢?看v来好像就是查询学生的服务自己在进行,但是背后日志记录对这些行行记录,但是查询学生的服务不知道存在q些记录q程Q这是我们要讨论AOP的目的所在。AOP的编E,好像是把我们在某个斚w的功能提出来与一批对象进行隔,q样与一批对象之间降低了耦合性,可以某个功能进行编E?br /> 我们直接从代码入手吧Q要实现以上的目标,我们可以使用一个动态代理类(Proxy)Q通过拦截一个对象的行ؓq添加我们需要的功能来完成。Java中的java.lang.reflect.Proxycdjava.lang.reflect.InvocationHandler接口为我们实现动态代理类提供了一个方案,但是该方案针对的对象要实现某些接口;如果针对的目的是cȝ话,cglib为我们提供了另外一个实现方案。等下会说明两者的区别?br />一、接口的实现ҎQ?br />1Q首先编写我们的业务接口QStudentInfoService.javaQ:
public interface StudentInfoService{
void findInfo(String studentName);
}
及其实现c(StudentInfoServiceImpl.javaQ:
public class StudentInfoServiceImpl implements StudentInfoService{
public void findInfo(String name){
System.out.println("你目前输入的名字?"+name);
}
}
2Q现在我们需要一个日志功能,在findInfo行ؓ之前执行q记录其行ؓQ那么我们就首先要拦截该行ؓ。在实际执行的过E中用一个代理类来替我们完成。Java中ؓ我们提供了实现动态代理类的方案:
1'处理拦截目的的类QMyHandler.javaQ?br />import org.apache.log4j.Logger;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
public class MyHandler implements InvocationHandler{
private Object proxyObj;
private static Logger log=Logger.getLogger(MyHandler.class);
public Object bind(Object obj){
this.proxyObj=obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
Object result=null;
try{
//请在q里插入代码Q在Ҏ前调?br /> log.info("调用log日志Ҏ"+method.getName());
result=method.invoke(proxyObj,args); //原方?br /> //请在q里插入代码Q方法后调用
}catch(Exception e){
e.printStackTrace();
}
return result;
}
}
2'我们实现一个工厂,Z方便我们使用该拦截类(AOPFactory.java)Q?br />public class AOPFactory{
private static Object getClassInstance(String clzName){
Object obj=null;
try{
Class cls=Class.forName(clzName);
obj=(Object)cls.newInstance();
}catch(ClassNotFoundException cnfe){
System.out.println("ClassNotFoundException:"+cnfe.getMessage());
}catch(Exception e){
e.printStackTrace();
}
return obj;
}
public static Object getAOPProxyedObject(String clzName){
Object proxy=null;
MyHandler handler=new MyHandler();
Object obj=getClassInstance(clzName);
if(obj!=null) {
proxy=handler.bind(obj);
}else{
System.out.println("Can't get the proxyobj");
//throw
}
return proxy;
}
}
3)基本的拦截与其工厂我们都实现了,现在试QClientTest.javaQ:
public class ClientTest{
public static void main(String[] args){
StudentInfoService studentInfo=(StudentInfoService)AOPFactory.getAOPProxyedObject("StudentInfoServiceImpl");
studentInfo.findInfo("阉K");
}
}
输出l果Q看你的log4j讄Q:
[INFO]调用log日志ҎfindInfo
你目前输入的名字?阉K
q样我们需要的效果出来了Q业务处理自己在q行Q但是我们实C日志功能Q而业务处?StudentInfoService)Ҏ不知道存在该行ؓ的。但是Java中提供的动态代理类的实现是针对实现了某些接口的c,如果没有实现接口的话Q不能创Z理类Q看以上部分Q?br />return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
看到了没有?obj.getClass().getInterfaces()要求实现了某些接口。以下提供哪些没有实现接口的实现ҎQ?br />
二、子cȝ实现Ҏ?br /> 首先Q请上网下CGLib的包Q?a >http://sourceforge.net/project/showfiles.php?group_id=56933 。设|好classpath路径QCGLib与java标准库提供的实现Ҏ不同Qcglib主要是基于实现类Q如StudentInfoServiceImpl.java)扩展一个子cL实现。与Dynamic Proxy中的Proxy和InvocationHandler相对应,net.sf.cglib.proxy.Enhancer和MethodInterceptor在CGLib中负责完成代理对象创建和Ҏ截获处理,产生的是目标cȝ子类而不是通过接口来实现方法拦截的QEnhancer主要是用于构造动态代理子cL实现拦截QMethodInterceptorQ扩展了Callback接口Q主要用于实现around adviceQAOP中的概念Q:
1Q我们的业务处理QStudentInfoServiceImpl.javaQ:
public class StudentInfoServiceImpl{
public void findInfo(String name){
System.out.println("你目前输入的名字?"+name);
}
}
2Q实行一个工h处理日志功能QAOPInstrumenter.javaQ:
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import org.apache.log4j.Logger;
public class AOPInstrumenter implements MethodInterceptor{
private Logger log=Logger.getLogger(AOPInstrumenter.class);
private Enhancer enhancer=new Enhancer();
public Object getInstrumentedClass(Class clz){
enhancer.setSuperclass(clz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable{
log.info("调用日志Ҏ"+method.getName());
Object result=proxy.invokeSuper(o,args);
return result;
}
}
3Q我们来试一下(AOPTest.javaQ:
public class AOPTest{
public static void main(String[] args){
AOPInstrumenter instrumenter=new AOPInstrumenter();
StudentInfoServiceImpl studentInfo=(StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class);
studentInfo.findInfo("阉K");
}
}
输出l果与以上相同?br /> CGLib中ؓ实现以上目的Q主要提供的c?br />1)EnhancerQsetCallback(Callback) ,setSuperclass(Class) ,create()q回动态子cObject
2)MethodInterceptor必须实现的接口:intercept(Object,Method,Object[],MethodProxy)q回的是原方法调用的l果。和Proxy原理一栗?/p>
三、以上的两个单实现AOP的方案都Z准备好了Q你可以自己~写试一下,以下单介l一下AOP的基本概念:
1QaspectQ切面)Q实Ccross-cutting功能Q是针对切面的模块。最常见的是logging模块Q这PE序按功能被分ؓ好几层,如果按传l的l承的话Q商业模型承日志模块的话根本没有什么意义,而通过创徏一个logging切面可以用AOP来实现相同的功能了?br />2QjointpointQ连接点Q:q接Ҏ切面插入应用E序的地方,该点能被Ҏ调用Q而且也会被抛出意外。连接点是应用程序提供给切面插入的地方,可以d新的Ҏ。比如以上我们的切点可以认ؓ是findInfo(String)Ҏ?br />3QadviceQ处理逻辑Q:advice是我们切面功能的实现Q它通知E序新的行ؓ。如在logging里,logging advice包括logging的实C码,比如像写日志C个文件中。advice在jointpoint处插入到应用E序中。以上我们在MyHandler.java中实Cadvice的功?br />4QpointcutQ切点)Qpointcut可以控制你把哪些advice应用于jointpoint上去Q通常你用pointcuts通过正则表达式来把明昄名字和模式进行匹配应用。决定了那个jointpoint会获得通知?br />5QintroductionQ允许添加新的方法和属性到cM?br />6QtargetQ目标类Q:是指那些用advice的类Q一般是指独立的那些商务模型。比如以上的StudentInfoServiceImpl.
7)proxyQ代理类Q:使用了proxy的模式。是指应用了advice的对象,看v来和target对象很相伹{?br />8Qweaving(插入Q:是指应用aspectsC个target对象创徏proxy对象的过E:complie timeQclassload timeQruntime
Spring的功能是很强大的Q在其“绝不发明自p为好的轮子,而只发明自己认ؓ不好的轮子”的指导思想下,通过充分实践了“一切实事求是、‘@证架构’的工作方式”的理论Q基本上把轻量的J2EE应用框架Q如ORM、MVC{)q行了整合,q构架了一些常用的功能(如DAO)QŞ成了一个功能强大的J2EE轻量U企业应用框架?br /> 然而,或许是大家对Spring掌握得还不透彻的缘故吧Q看到很多Y件企业中用到的Spring功能Q基本上大多数都只是用其IOC功能Q有时候附带用了其中的AOP事务理功能?br /> IOC及AOP虽然不是Spring首创Q然而其在这两块都是做得很不错的Q应该说整个Spring框架是围绕着其IOC实现及AOP实现架设h的。我惻I深入挖掘IOC、AOP以及Spring中的实现Q用等Q对于初学者帮助会非常大,因此Q从本期开始,大的《玩玩Springpd》将伴随大家一赯qIOC及AOP的世界?br /> ׃本h水^有限Q文中难免有很多不甚至错误之处Q还请各位朋友不吝批评指教?br /> 一、IOC?/b> IOC-全称Inversion of ControlQ中文解释:控制反{。另外,IOC又称DI(全称)Dependency InjectionQ中文解释:依赖注入?br /> 呵呵Q这些名词搞得有点像学古文的味道哈。很多大师还都说IOC中有一个著名的好莱坞理论:你呆着别动Q到时我会找你。你呆着别动Q到时我会找你。由于本人未到过好莱坞参加过C会实践Q因此,q句话理解有点困难?br /> IOC是一U新的设计模式,即IOC模式Q系l中通过引入实现了IOC模式的IOC容器Q即可由IOC容器来管理对象的生命周期、依赖关pȝQ从而得应用程序的配置和依赖性规范与实际的应用程序代码分开。其中一个特点就是通过文本的配件文件进行应用程序组仉怺关系的配|,而不用重C改ƈ~译具体的Java代码?br /> 当前比较知名的IOC容器有:Pico Container、Avalon 、Spring、JBoss、HiveMind、EJB{,国内由板桥里责的国开源项目Jdon框架Q也是具有IOC容器功能(׃没来得及认真研读其源码,gjdon中IOC部䆾是调用Pico的IOC容器功能来实现的)?br /> 在上面的几个IOC容器中,轻量U的有Pico Container、Avalon、Spring、HiveMind{,重量的有EJBQ而半d重的有容器有JBossQJdon{?br /> IOCI竟是什么?IOC是如何生的?用在什么场?Z么我们以前不用IOCQ而现在要用IOCQ“物有本末,事有l始”,Z更加透彻的理解这一问题Q大峡打从自己所理解的面向对?OO)设计及编E发展历E来q行分析Q也许这栯让IOC的初学者更加了解IOC的发展的前因后果Q争取做到“知其然Q知其所以然Q其然!”?br /> 若大家等不急了Q就直接癑ֺ一下有关IOC的其它文章,q方面国内很多先׃已经作了很多介绍。如C的《IOC详解》、板桥里人的设计模式及IOC理论{?br /> 二、 最老的OO~程 记得曄看《Think in Java》最早版本的时候,里面有这么一句让人振奋话Q一切都是对象。这时我们OO~程的核心是围绕着面向对象~程的三个特性即“扎쀝、“封装”、“多态”来展开的?br />2.1 装 那时我们学会了对现实q事物及Y件模型进行了抽象。比如要描述一只猫Q那么这支猫应该有“颜艜y、“重量”、“公母”、“脾气”、“出生日期”等属性,另外q有“跑”、“吃”、“叫”、“猫捉老鼠”等Ҏ。如Java代码来表C,大致是如下Q?br />public Class Cat { private String color;//颜色 private String weight;//重量 private String sex;//公母 private String temper;//脾气 private String birthday;//出生日期 private void run ();//?br />private void eat (Food food); //?食物) private void shout(int type);//?cd) private boolean chase(Mice mice);//猫捉老鼠 } 2.2 l承 最早的OO~程时期Q我们还会引入承,q经帔R励大家多用l,认ؓl承是OO~程思想的核心。承的核心是围绕着如何把类与类之间h共同Ҏ的部䆾抽象到基cM。认样不但能使用了OO的特性,q减了很多子类的代码?br /> 我们通过日常生活的常识知道,猫是一U动物,因此动物有的Ҏ他基本上都有。于是,如果我们的系l中不但有猫Q还会有很多其它的动物出现。我们就会设计一个动物类Q把所有动物的共性抽象到一个基cM。这里,猫及动物基类的代码大致如下: public abstract Class Animal{ private String color;//颜色 private String weight;//重量 private String sex;//公母 private String temper;//脾气 private String birthday;//出生日期 private void run ();//?br />private void eat (Food food); //?食物) private void shout(int type);//?cd) } public Class Cat extends Animal private int power;//能力 private int agility;//敏捷?br /> // 猫捉老鼠是特有的Ҏ private boolean chase(Mice mice) { return true; }; } 2.3 多?/b> q时我们q会不时使用到OO的另外一个特性多态。多态是很重要的一门技术,然而很多时候却没有很好的理解ƈ使用Q回头看以前的代码,我们看到有很多地方属于故弄玄虚的嫌疑?br /> 接上面的例子Q假如我们要写一个喂d?有猫、狗、猪、v、老鼠{?的程序。利用Java的多态特性,我们的大致代码如下: public class PetManage { //喂食我的宠物 public void feeding(Animal a) { } /** * @param args */ public static void main(String[] args) { Animal myPet=new Cat(); PetManage pm=new PetManage(); pm.feeding(myPet); } } 通过使用多态特性,哪一天若我们的不喜欢猫,而是喜欢ȝ的时候,只要把new Cat()变成new Pig()Q即可?br /> 2.4 对象生命周期 q一阶段的OOE序中,我们知道要用一个对象的时候,p使用Java中的关键字new来生成一个来用即可。OO对于我们来说Q一切都是那么简单,很多时候甚x觉OO跟OP的编E方法也没太大区别。代码如下: Cat myCat=new Cat();//创徏一支具体的?br />myCat.shout();//叫一?br /> 此时Q我们对Java虚拟是非怿ȝQ我们的思想也很单纯Q我们知道Java对象的生命开始于new关键词。我们不太关心对象生命的l束Q我们知道Java有一个比C语言历害、智能化的垃圾收集器Q他会帮我们自己的清理内存中不用的对象?br /> 当然Q也有的人由于对垃圾攉器忠诚度的怀疑,不放心垃圾收集器的能力,于是在程序中l常要加一句类似“myPet=null”的代码来结束对象的生命?br /> 当然Q我们也知道有一些外部资源如数据库连接等Q需要手动熟悉资源。于是知道在使用cM资源的时候必都加上一句:conn.close()Q有时候还要在close()后面再加一句:conn=null。呵呵,非常有意思?br /> 2.5结 现在看来Q其实那时确实犯了很多幼E的错误Q也C不少的弯路,做了很多画蛇添的工作,写了很多难与l护的代码?br /> Ҏ今天的IOC模式Q若要从早的OOҎ中硬要找一个类似Spring的容器的话,那就是:“程序员QJVM本n”。是E序员以及JVM一h们管理对象的生命周期、对象之间的关系{。那时候若有Q何变动都需要改代码Q(虽然好的设计代码修改会非常少Q但也得改!Q,然后~译Q然后拿到测试环境及用户环境中执行。如此反复,q日复一日、年复一q?br /> 那时我们的代码复用用得最多的是OO的承功能,另外q有很多OPҎ中带q来的函数?br /> 本文中涉及到的几个简单源码,请到EasyJF开源团队官|下载,地址Q?br /> http://www.easyjf.com/html/bbs/20060602/12718636-1843943.htm?ejid=1287314863003738 |