两个问题
1.spring的依赖注入
在applicationcontext.xml中配置bean,注入需要组件,与直接在bean的类中new一个实例,到底有什么不同?2.接口和实现类
许多spring的例子中,一个模块都是先写一个接口,在写继承这个接口的实现类,为什么要这样写?请大哥详细解释一下
1.spring的依赖注入
在applicationcontext.xml中配置bean,注入需要组件,与直接在bean的类中new一个实例,到底有什么不同?2.接口和实现类
许多spring的例子中,一个模块都是先写一个接口,在写继承这个接口的实现类,为什么要这样写?请大哥详细解释一下
1.spring的依赖注入
写在配置文件里 是为了解耦合
2.接口和实现类
spring的思想就是代理模式 他的实现类不一定是你的类 也许只是实现你接口的类说起来挺复杂的 自己看看源码就明白了
2.第2个我也没搞懂,有人说类的实例化经历了new->interface->factory->ioc的过程,还没搞懂spring中ioc可以直接指定具体的实现类了,为啥写的时候还是多写个接口。
interface A
{
}
class B implements A
{
}class Test
{
public void static main(String[] a){
A a=new B();
}
}
这样的话..要是我要建一个新的类C..要去实例化..那么我main方法也要改动..既然改了就要重新编译...
而反射的话直接是改字符串的..forName("A")的..这样的话你可以在配置文件里进行改动..你需要实例化哪个类就哪个吧哈..不用再重新编译了...第2个不那么好解释哈
现在只能告诉你
不用new 的好处就是 方便了解耦合
我们写抽象类, 写接口就是为了一件事 “接耦合”
既然我们吧所有可以独立起来的 类放在了ioc里面了 我们就可针对某个类的需要给他注入
如:
Action 注入 Biz
那样就实现了 既通过了解耦合又 达到了
代码的清晰度(统一性) 和规范 ,要的时候就从ico中那就是了
而且当你 类库庞大的时候 这样的好处就会慢慢体现出来了
不是无聊哦.. IOC只是一方面 重点在AOP上..有些时候 我们写的程序代码 一但编译成CLASS 那么想修改的话 必须得重新再编译 并且替换..如果说通过修改XML文件而成功修改一个对象的实现 那多好啊 而且 重点在于 这是由SPRING代替你创建的对象 当你用到AOP的时候 你就会知道 这些有什么用处了 或许他这些特性都没有提供给我们啥特殊的功能啊 啥特殊的方便啊 但是 只是现在体会不到而已吧..
假如 写了一个class AuctionManagerImpl有一个依赖注入
方法 private AuctionUserDao userDao;
public void setUserDao(AuctionUserDao userDao)
{
this.userDao = userDao;
}
xml
<bean id="auctionManager"
class="org.crazyjava.auction.service.impl.AuctionManagerImpl">
<!-- 为业务逻辑组件注入所需的DAO组件 -->
<property name="userDao" ref="auctionUserDao"/>
</bean>
<bean id="auctionUserDao" parent="daoTemplate"
class="org.crazyjava.auction.dao.impl.AuctionUserDaoHibernate"/>类AuctionManagerImpl使用了AuctionUserDaoHibernate的实例auctionUserDao,现在如果AuctionUserDaoHibernate改成其他名称,只需相应的更改bean配置就行了,而如果用
public void setUserDao(AuctionUserDao userDao)
{
//this.userDao = userDao;
this.userDao =new AuctionUserDaoHibernate();
}
就需要改AuctionManagerImpl类文件,且需重新编译AuctionManagerImpl。
是这样的优势之处吗?
而且使用泛型会更加简化我们的编码和达到通用的效果
例如
/**
* 泛型Dao(Data Access Object)接口<br>
* 定义通用的Create,Retrive,Update,Delete,List等操作
*
* @author totong
* @since 2007-5-13
*
* @param <ENTITY>
* 实体的类型
* @param <ID>
* 主键的类型
*/
public interface Dao<ENTITY, ID extends Serializable> { /**
* 通过主键标识查找某个对象
*
* @param id
* 对象标识
* @return 实体
*/
ENTITY findById(ID id); /**
* 通过主键标识查找某个对象,可以锁定表中对应的记录
*
* @param id
* 对象标识
* @param lockMode
* 锁定的方式
* @return 实体
*/
ENTITY findById(ID id, LockMode lockMode); /**
* 得到所有的对象
*
* @return 实体集合
*/
List<ENTITY> findAll(int firstResult, int maxResults);
/**
* 得到所有的对象
*
* @return 实体集合
*/
List<ENTITY> findAll(); /**
* 通过给定的一个对象,查找与其匹配的对象。
*
* @param entity
* 实体
* @return 实体集合
*/
List<ENTITY> findByExample(ENTITY entity); /**
* 通过给定的一个对象,查找与其匹配的对象。
*
* @param entity
* 实体
* @param firstResult
* 第一条记录
* @param maxResults
* 最大记录数
* @param matchMode
* 匹配模式
* @return 实体集合
*/
List<ENTITY> findByExample(ENTITY entity, int firstResult, int maxResults,
MatchMode matchMode); /**
* 通过给定的一个对象,查找与其模糊匹配的对象。
*
* @param entity
* 实体
* @return 实体集合
*/
List<ENTITY> findByExampleLikeAnyWhere(ENTITY entity); /**
* 通过给定的属性名和值,查找与其匹配的对象。
*
* @param propertyName
* 属性名
* @param value
* 属性值
* @return 实体集合
*/
List<ENTITY> findByProperty(String propertyName, Object value); /**
* 通过给定的属性名和值的键值对,查找与其匹配的对象。
*
* @param properties
* 属性映射
* @return 实体集合
*/
List<ENTITY> findByProperties(Map<String, Object> properties); /**
* 持久化对象
*
* @param entity
* 实体
*/
void saveOrUpdate(ENTITY entity); /**
* 删除对象
*
* @param entity
* 实体
*/
void delete(ENTITY entity); /**
* 将entity持久化
*
* @param entity
* 实体
*/
void update(ENTITY entity); /**
* 返回entity的持久化对象,并不持久化entity
*
* @param entity
* 实体
* @return 实体
*/ ENTITY merge(ENTITY entity); /**
* 持久化entity,返回对象标识
*
* @param entity
* 实体
* @return 对象标识
*/
ID save(ENTITY entity); /**
* 重新读取对象
*
* @param entity
* 实体
*/
void refresh(ENTITY entity); /**
* 取得记录数
*
* @return 记录数
*/
Integer count();
/**
* 根据属性条件取得对应的记录数
* @param propertyName
* @param value
* @return
*/
Integer countByProperty(String propertyName, Object value); /**
* 根据多个属性查询
*
* @param properties
* 属性映射
* @param firstResult
* 第一条记录
* @param maxResults
* 最大记录数
* @return 实体集合
*/
List<ENTITY> findByProperties(Map<String, Object> properties,
int firstResult, int maxResults);
}
AOP用动态代理 目标功能类必须实现一个接口可以通过cglib来实现 就不需要接口
为什么要引入它,在没用spring的时候,比如UserManager 中有一个LogManager的属性,如果你要用LogManager中的方法,那你就必须去new然后才能使用 LogManager lm = new LogManager();也许你觉得这没什么new就new呗,但是如果你的UserManager 如果要进行事务控制、权限检查还要依赖很多很多类,你是不是也一个个new呢(其实挺麻烦的),现在有的spring,你所依赖的那些类不用你在new了,还是spring容器初始化的时候,它会一一帮你new好,然后注入给UserManager。 这也就体现了依赖注入当然还有一个Ioc的概念就是控制反转,以前没用spring容器的所有的程序都是你自己控制,现在许多的类都交有spring去管理、控制了,所以大概就有这么个意思在里面。代码写多了好像这概念就明了了,能懂吗 ?
为什么要这样做,其实它是一种面向接口编程。。 这样让你和客户都不依赖具体的实现而依赖接口
比如你做的项目中有一个 业务逻辑层com.fjh.manager 然后有一个具体的实现com.fjh.manager.impl
由于你的业务逻辑层是要和数据库打交道的,如果你不定义接口的话,假如持久层你用的是hibernate技术的话,就写一个实现类,那么这样代码是不是就写死了,假如你的客户要求持久层技术要求变换换成JDO、iBatis等,那么你现在是不是要重写你的业务逻辑类。。但是如果你抽象出一个接口的话,那么要换,代码不用变,你只要再增加一个下其他持久层框架的实现与一些配置信息就可以了。接口可以不用做任何方法,更重要的是你呈现层(比如action)调用业务逻辑方法它面向的也是接口代码也不会变,但是你如果就现在一个具体实现类,呈现层中的代码的方法和参数是不是会改变呢。这样系统弄得一团糟。。面向接口编程上面还是一个好处。其实他的好处非常大。这样也是面向对象编程的一个原则吧:就是依赖倒置原则(DIP)
大致的要求就是:A、高层模块不应该依赖于底层模块。二者都应该依赖于抽象。
B、抽象不应该依赖于细节。细节应该依赖于抽象。
这样代码比较清晰、灵活,而且程序的扩展性非常强哦
说的有点多。高手别笑啊
2、用接口是为了使用JDK的动态代理机制,SPRING的AOP就是用的JDK动态代理机制,如果不用接口也行,
不过要引入CGLIB包,使用CGLIB才能使用JDK动态代理。
2.面向接口的思想,接口中的方法在不同的地方被实现,据有不同的行为,因为你不知道什么时候要用这些方法。