Spring学习笔记(一)
Spring五个功能:
基本的xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="greetingServiceProp" class="com.spring.chapter01.helloworld.GreetingServiceImpl"> <property name="greeting" value="world-prop"></property> </bean> <bean id="greetingServiceArg" class="com.spring.chapter01.helloworld.GreetingServiceImpl"> <constructor-arg value="world-arg"></constructor-arg> </bean> </beans>
可以通过两种方式设置属性值:
property通过类的setter方法赋值,name为属性名称,value为赋值的参数,ref为非基本类型的引用
constructor-arg通过类的构造方法赋值,value为构造方法的参数,如果有多个参数,用多个constructor-arg标签即可
public class GreetingServiceTest { public static void main(String[] args) { XmlBeanFactory factory = new XmlBeanFactory( new ClassPathResource( "com/spring/chapter01/helloworld/applicationContext.xml")); /*XmlBeanFactory factory = new XmlBeanFactory( new FileSystemResource( "path..."));*/ GreetingService greetingService = (GreetingService) factory .getBean("greetingServiceArg"); greetingService.sayGreeting(); } }
通过XmlBeanFactory可以构造一个工厂,xml文件可以通过ClassPathResource或者FileSystemResource两种方式获得,第一种是到类的路径下查找,第二种是在文件系统中查找,factory通过调用getBean获得具体的对象,参数为bean中的id值,之后就可以调用具体对象的方法了。
理解依赖注入
降低类之间的耦合,可以使用接口实现解耦合,将协调依赖对象之间合作的责任从对象自身中转移出来。
具体类(这里定义了一个圆桌骑士,继承自通用的骑士接口):
public class KnightOfTheRoundTable implements Knight{ private String name; private Quest quest; public void setQuest(Quest quest){ this.quest = quest; } public String getName(){ return this.name; } public KnightOfTheRoundTable(String name){ this.name = name; } @Override public Object embarkOnQuest() { return quest.embark(); } }
定义任务:
public class HolyGrailQuest implements Quest{ @Override public Object embark() { return new HolyGrail(); } }
定义奖励(圣杯):
public class HolyGrail { public HolyGrail(){ System.out.println("get the Grail"); } }
骑士类中有一个任务quest,骑士不需要自己去获取任务,xml配置文件中将把任务赋给这个骑士。
<bean id="quest" class="com.spring.chapter01.knight.HolyGrailQuest"> </bean> <bean id="knight" class="com.spring.chapter01.knight.KnightOfTheRoundTable"> <constructor-arg value="zyd"></constructor-arg> <property name="quest" ref="quest"></property> </bean>
通过xml配置文件将HolyGrailQuest这个任务赋给了圆桌骑士zyd,这下zyd可以去执行任务了。
依赖注入是一种松散耦合代码,这样可以尽可能的保持应用对象之间的疏远关系,比如这里骑士就不知道自己会分到什么任务,完全由xml文件决定,提高了可拓展性。
AOP:面向切面编程
由于系统由许多组件组成,每个组件负责一部分功能,有些组件常常带有一些除了核心功能之外的附加功能(如日志,安全),并融入到其他模块中,这种系统服务通常叫做交叉业务,使得代码变得复杂。
AOP帮助我们将这些服务模块化,使得这些组件更加专注于自己的业务,以至于核心业务感受不到附加功能的存在,使其分离。
为每个骑士增加一个吟游诗人:
public class Minstrel { private static final Logger SONG = Logger.getLogger(Minstrel.class); public void singBefore(Knight knight) { System.out.println(knight.getName() + " so brave!"); } public void singAfter(Knight knight) { System.out.println(knight.getName() + " achieved the quest"); } }
在骑士出发和归来的时候分别调用singBefore和singAfter方法,为骑士吟唱。但是有个问题,骑士不应该等待吟游诗人吟唱完了再出发(如果吟游诗人不吟唱的话骑士也应该出发完成任务),吟游诗人也不应该等待通知再写谱子,所以这两个类应该是互不干扰的。
将Minstrel转化为切面可以解决这个问题
首先声明命名空间(加粗大号字体):
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
使用aop创建bean:
<!-- 声明minstrel bean --> <bean id="minstrel" class="com.spring.chapter01.knight.Minstrel"> </bean> <aop:config> <!-- 创建minstrel切面 --> <aop:aspect ref="minstrel"> <!-- 创建切入点来绑定embarkOnQuest() 方法由minstrel提供 --> <aop:pointcut expression="excution(* *.embarkOnQuest(..) and target(bean))" id="questPointcut" /> <!-- 吟唱前编织 --> <aop:before method="singBefore" pointcut-ref="questPointcut" arg-names="bean" /> <!-- 吟唱后编织 --> <aop:after-returning method="singAfter" pointcut-ref="questPointcut" arg-names="bean" /> </aop:aspect> </aop:config>
在骑士执行embarkOnQuest的之前和之后,会分别执行Minstrel的singBefore和singAfter方法。
小结
为了提供松散耦合的代码,最重要的就是依赖注入和AOP
依赖的对象如果只能通过接口知道所注入的对象,那么耦合就会非常少。
在Spring装配Bean时,使用切面可以有效的赋予Bean新的行为。
优质内容筛选与推荐>>