Spring学习笔记(一)


Spring五个功能:

  1. 轻量级
  2. 依赖注入:提供了一种松耦合技术
  3. 面向切面:将业务逻辑从应用服务中分离出来,应用对象只做他们该做的
  4. 容器:管理应用对象的生命周期和配置
  5. 框架:通过xml文件配置组合,使开发人员专注于开发应用逻辑

基本的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新的行为。

优质内容筛选与推荐>>
1、一起学英语 -> 前言
2、数据库连接字符串
3、《世界是数字的》读后感
4、C# wm6通过udp协议和pc通讯
5、总结篇:width与margin,padding之间的宽度计算问题区别


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn