spring 解读之 DI 、AOP

本文深入探讨Spring框架中的依赖注入(DI)和面向切面编程(AOP)技术。详细介绍了Spring支持的三种依赖注入方式:接口注入、构造方法注入和setter方法注入,并解析了AOP的概念及其实现方式。

1.依赖注入

使用依赖注入,对象的依赖都是在对象创建时由负责协调应用的各个对象的外部实体提供的。这就是依赖被注入到对象中。DI意味着关于对象如何获得他的协作对象的责任被反转了。

DI的关键有点是松解耦合。如果一个对象通过接口只知道其依赖对象,那么该依赖将使用一种不同的实现方式来交互,其依赖对象并不知道这种变化。

简而言之:依赖注入就是   协调依赖对象之间合作的责任从对象自身中转移出来

1.1 spring依赖注入(DI)的三种方式,分别为:

1.  接口注入

2.  Setter方法注入

3.  构造方法注入


Type1 接口注入
我们常常借助接口来将调用者与实现者分离。如:
[java]  view plain  copy
 print ?
  1. public class ClassA     
  2. {  
  3.      private InterfaceB clzB;    
  4.   
  5.      public init()     
  6.     {  
  7.       Ojbect obj =Class.forName(Config.BImplementation).newInstance();    
  8.       clzB = (InterfaceB)obj;  
  9.     }    
  10. }   

上面的代码中,ClassA依赖于InterfaceB的实现,如何获得InterfaceB实现类的实例?传统的方法是在代码中创建InterfaceB实现类的实例,并将起赋予clzB.

而这样一来,ClassA在编译期即依赖于InterfaceB的实现。为了将调用者与实现者在编译期分离,于是有了上面的代码,我们根据预先在配置文件中设定的实现类的类名,动态加载实现类,并通过InterfaceB强制转型后为ClassA所用。


Type2构造子注入:
首先,我们写一个PersonDao.java接口:
[java]  view plain  copy
 print ?
  1. public interface PersonDao {  
  2.     public void add();  
  3. }  
并对这个接口进行实现:
[java]  view plain  copy
 print ?
  1. public class PersonDaoBean implements PersonDao{  
  2.   
  3.     @Override  
  4.     public void add() {  
  5.         System.out.println("我是PersonDaoBean中的add()方法");  
  6.           
  7.     }  
  8.   
  9. }  

然后,我们写一个PersonService.java接口:
[java]  view plain  copy
 print ?
  1. public interface PersonService {  
  2.     public  void save();  
  3. }  
并对这个接口进行实现:

[java]  view plain  copy
 print ?
  1. public class PersonServiceBean implements PersonService {  
  2.     private PersonDao personDao;  
  3.     private String name;  
  4.       
  5.     public PersonServiceBean(){}  
  6.     public PersonServiceBean(PersonDao personDao, String name) {  
  7.         this.personDao = personDao;  
  8.         this.name = name;  
  9.     }  
  10.     public PersonDao getPersonDao() {  
  11.         return personDao;  
  12.     }  
  13.     public void setPersonDao(PersonDao personDao) {  
  14.         this.personDao = personDao;  
  15.     }  
  16.     public String getName() {  
  17.         return name;  
  18.     }  
  19.     public void setName(String name) {  
  20.         this.name = name;  
  21.     }  
  22.   
  23.     @Override  
  24.     public void save(){  
  25.         personDao.add();  
  26.         System.out.println(name);  
  27.         //personDao.add();  
  28.     }  
  29. }  

可以看到,在这个实现类中,我们引入了一个PersonDao类型的属性和一个String类型的属性,并且建造了一个包含这两个参数的构造函数和setter、getter方法。
然后,我们在beans.xml中进行配置:
[html]  view plain  copy
 print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"      
  3.     xsi:schemaLocation="http://www.springframework.org/schema/beans      
  4.     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd      
  5.     http://www.springframework.org/schema/context      
  6.     http://www.springframework.org/schema/context/spring-context-2.5.xsd  
  7.     http://www.springframework.org/schema/context     
  8.     http://www.springframework.org/schema/context/spring-context-2.5.xsd">     
  9.       
  10.     <bean id="personDao" class="cn.itcast.dao.impl.PersonDaoBean"></bean>  
  11.     <bean name="personService" class="cn.itcast.service.impl.PersonServiceBean">  
  12.         <constructor-arg  index="0" type="cn.itcast.dao.PersonDao" ref="personDao"></constructor-arg>  
  13.         <constructor-arg index="1" value="itcast" />  
  14.     </bean>  
  15. </beans>  
可以看到,我们配置了两个bean:
第一个bean是依赖bean,我们在PersonServiceBean.java类中需要依赖这个bean指向的类

第二个bean是我们要用到的bean,然后在这个bean中我们配置了两个<constructor-arg>标签:其中index表明索引,就是构造函数中参数的索引,0代表第一个参数;type表明这个参数的类型,ref表明需要依赖于哪个类。第二个中没有type和ref,是因为String类型不需要指定type,另外也不是依赖类,所以也不需要ref属性了。


Type3  setter设值注入

首先,我们写一个PersonService.java接口
[java]  view plain  copy
 print ?
  1. public interface PersonService {  
  2.     public abstract void save();  
  3. }  

然后,我们为这个接口写一个实现类:PersonServiceBean.java
[java]  view plain  copy
 print ?
  1. public class PersonServiceBean implements PersonService {  
  2.   
  3.     private String name;  
  4.   
  5.     public String getName() {  
  6.         return name;  
  7.     }  
  8.     public void setName(String name) {  
  9.         this.name = name;  
  10.     }  
  11.   
  12.     @Override  
  13.     public void save(){  
  14.         System.out.println(name);  
  15.         //personDao.add();  
  16.     }  
  17. }  
我们编辑beans.xml文件,配置IOC反转容器的xml代码:
[html]  view plain  copy
 print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"      
  3.     xsi:schemaLocation="http://www.springframework.org/schema/beans      
  4.     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd      
  5.     http://www.springframework.org/schema/context      
  6.     http://www.springframework.org/schema/context/spring-context-2.5.xsd  
  7.     http://www.springframework.org/schema/context     
  8.     http://www.springframework.org/schema/context/spring-context-2.5.xsd">     
  9.       
  10.     <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">  
  11.         <property name="name" value="itcast" />     
  12.     </bean>  
  13.       
  14. </beans>  
原理:通过beans.xml我们配置了IOC反转容器,配置的属性通过setter方法进行注入。如果没有setter方法会报错。

依赖注入只是spring提供的一种技术,它支持松散耦合。面向切面编程技术提供了另外一种解耦和的功能,他将功能和对象分开。

2.面向切面编程


AOP帮助我们将服务模块化,确保了POJO简单。使用AOP可以使用各种功能层来覆盖核心业务层。
面向切面编程(也叫面向方面),可以通过预编译方式和运行期 动态代理 实现在 不修改源代码的 情况下给程序动态统一添加功能 的一种技术。
面向切面编程:就是在原直线编程的某处咔嚓一下,加点动西,而且不影响原来的代码。可以用在日志,加权限,事物,异常管理等方面。

小结:
DI是联合对象的一种方法,例如对象无需知道依赖来自何处或者依赖如何实现。不同于机子获得依赖对象,被依赖的对象被赋予他们所依赖的类。
spring装配bean时,这些切面将在运行中被编制,这样就可以非常有效的给予bean新的行为。
参考:http://blog.youkuaiyun.com/xn4545945/article/details/8241206
(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值