Spring 入门

示例

首先举个栗子,演示 Spring 的注入,项目工程视图如下
项目工程视图

定义一个Tutorial类

package com.ggli.aop.model;

public class Tutorial {
    private String name;
    private String url;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public void printName() {
        System.out.println("Tutorial name: " + this.name);
    }
    public void printUrl() {
        System.out.println("Tutorial url: " + this.url);
    }
    public void printThrowException() {
        throw new IllegalArgumentException();
    }
}

在关联 Spring 的 applicationContext.xml 中配置 bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="tutorial1" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Java Essential Training"/>
        <property name="url" value="https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"/>
    </bean>
    <bean id="tutorial2" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Overview of IDEs for Java"/>
        <property name="url" value="https://www.lynda.com/Development-Tools-tutorials/Overview-IDEs-Java/486760-2.html"/>
    </bean>
    <bean id="tutorial3" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Up and Running with Java Applications"/>
        <property name="url" value="https://www.lynda.com/Java-tutorials/Up-Running-Java-Applications/435790-2.html"/>
    </bean>
</beans>

使用 p 简化 bean 的属性赋值(convert to p-namespace)
首先,导入 p 的命名空间(不需要导入 xsi:schemaLocation

xmlns:p="http://www.springframework.org/schema/p"

bean 定义就可以写为

<bean id="tutorial1" class="com.ggli.aop.model.Tutorial" 
p:name="Java Essential Training" p:url="https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"/>

新建一个单元测试类

import com.ggli.aop.model.Tutorial;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UnitTest {

    @Test
    public void testObject() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Tutorial tutorial = (Tutorial) context.getBean("tutorial1");
        System.out.println("------------------------------");
        tutorial.printName();
        tutorial.printUrl();
        System.out.println("------------------------------");

        try {
            tutorial.printThrowException();
        } catch (Exception e) {

        }
    }
}

静态工厂方法配置 bean

Java 程序源码

package com.ggli.aop.fatory;

import java.util.HashMap;
import java.util.Map;

public class StaticFactoryMethod {
    public static Map<String, Tutorial> map = new HashMap<String, Tutorial>();

    static {
        map.put("Alice", new Tutorial(
        "Java Essential Training",
        "https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"));
        map.put("Grace", new Tutorial(
        "Overview of IDEs for Java",
        "https://www.lynda.com/Development-Tools-tutorials/Overview-IDEs-Java/486760-2.html"));
    }

    public static Tutorial getTutorial(String key){
        return map.get(key);
    }
}

xml 配置

<!-- static factory method -->    
<bean id="tutorial" factory-method="getTutorial" class="com.ggli.aop.fatory.StaticFactoryMethod">
    <constructor-arg value="Alice" type="java.lang.String"></constructor-arg>
</bean>

实例工厂方法配置 bean

Java 程序源码

package com.ggli.aop.fatory;

import java.util.HashMap;
import java.util.Map;

public class InstanceFactoryMethod {
    public static Map<String, Tutorial> map = new HashMap<String, Tutorial>();

    static {
        map.put("Alice", new Tutorial(
        "Java Essential Training",
        "https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"));
        map.put("Grace", new Tutorial(
        "Overview of IDEs for Java",
        "https://www.lynda.com/Development-Tools-tutorials/Overview-IDEs-Java/486760-2.html"));
    }

    public static Tutorial getTutorial(String key){
        return map.get(key);
    }
}

xml 配置

<!-- instance factory method -->
<bean id="method" class="com.ggli.aop.fatory.InstanceFactoryMethod"/>
<bean id="tutorial" factory-bean="method" factory-method="getTutorial" class="com.ggli.aop.fatory.StaticFactoryMethod">
    <constructor-arg value="Alice"></constructor-arg>
</bean>

AOP

Spring AOP 相当于一个拦截器,当一个方法执行时,Spring能够拦截正在执行的方法,在方法执行前或后增加额外的功能和处理。

Spring AOP 支持4种类型的通知

TypeDescription
before advice在方法执行前执行
after returning advice在方法执行返回一个结果后执行
after throwing advice在方法执行中抛出异常时执行
around advice在方法执行前后和抛出异常时执行,综合了上述三种

下面分别介绍。

before advice

创建一个实现 MethodBeforeAdvice 接口的类,该类实现 before 方法,当被拦截的方法执行前,该 before 方法会被执行。

package com.ggli.aop.advice;

import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;

public class BeforeAdvice implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("[Before method] " + o.getClass().getName() + "." + method.getName() + "()");
    }
}

在 Spring 的 applicationContext.xml 中,创建BeforeAdvice类对应的 bean,以及一个代理的 bean
设置两个 property

  • target:设置要拦截的 bean
  • interceptorNames:设置作用于 proxy/target 上的通知
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="tutorial1" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Java Essential Training"/>
        <property name="url" value="https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"/>
    </bean>

    <bean id="beforeAdvice" class="com.ggli.aop.advice.BeforeAdvice"/>

    <bean id="proxy1" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="tutorial1"/>
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
            </list>
        </property>
    </bean>
</beans>

after advice

创建一个实现 AfterReturningAdvice 接口的类,在被拦截的方法运行返回结果后将执行类中的 afterReturning 方法

package com.ggli.aop.advice;

import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;

public class AfterAdvice implements AfterReturningAdvice {
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("[After method] " + o1.getClass().getName() + "." + method.getName() + "()");
    }
}

修改 applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="tutorial1" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Java Essential Training"/>
        <property name="url" value="https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"/>
    </bean>

    <bean id="beforeAdvice" class="com.ggli.aop.advice.BeforeAdvice"/>
    <bean id="afterAdvice" class="com.ggli.aop.advice.AfterAdvice"/>

    <bean id="proxy1" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="tutorial1"/>
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
                <value>afterAdvice</value>
            </list>
        </property>
    </bean>
</beans>

after throwing advice

创建一个类实现 ThrowsAdvice 接口。

package com.ggli.aop.advice;
import org.springframework.aop.ThrowsAdvice;

public class ExceptionAdvice implements ThrowsAdvice {
    public void afterThrowing(IllegalArgumentException e) throws Throwable {
        System.out.println("[ExceptionAdvice] sends the regards: " + e.toString());
    }
}

修改 applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="tutorial1" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Java Essential Training"/>
        <property name="url" value="https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"/>
    </bean>

    <bean id="beforeAdvice" class="com.ggli.aop.advice.BeforeAdvice"/>
    <bean id="afterAdvice" class="com.ggli.aop.advice.AfterAdvice"/>
    <bean id="exceptionAdvice" class="com.ggli.aop.advice.ExceptionAdvice"/>

    <bean id="proxy1" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="tutorial1"/>
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
                <value>afterAdvice</value>
                <value>exceptionAdvice</value>
            </list>
        </property>
    </bean>
</beans>

around advice

创建一个类实现 MethodInterceptor 接口,需要在方法中执行 Object result = methodInvocation.proceed() 方法才能得到执行,否则方法不会执行。

package com.ggli.aop.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundAdvice implements MethodInterceptor {
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        try {
            System.out.println("[Around method] Before: " + methodInvocation.getMethod().getName());
            Object obj = methodInvocation.proceed();
            System.out.println("[Around method] After: " + methodInvocation.getMethod().getName());
            return obj;
        } catch (IllegalArgumentException e) {
            System.out.println("[Around method] Exception: " + methodInvocation.getMethod().getName());
            throw e;
        }
    }
}

修改 applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="tutorial1" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Java Essential Training"/>
        <property name="url" value="https://www.lynda.com/Java-tutorials/Java-Essential-Training/377484-2.html"/>
    </bean>
    <bean id="tutorial2" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Overview of IDEs for Java"/>
        <property name="url" value="https://www.lynda.com/Development-Tools-tutorials/Overview-IDEs-Java/486760-2.html"/>
    </bean>
    <bean id="tutorial3" class="com.ggli.aop.model.Tutorial">
        <property name="name" value="Up and Running with Java Applications"/>
        <property name="url" value="https://www.lynda.com/Java-tutorials/Up-Running-Java-Applications/435790-2.html"/>
    </bean>

    <bean id="beforeAdvice" class="com.ggli.aop.advice.BeforeAdvice"/>
    <bean id="afterAdvice" class="com.ggli.aop.advice.AfterAdvice"/>
    <bean id="exceptionAdvice" class="com.ggli.aop.advice.ExceptionAdvice"/>
    <bean id="aroundAdvice" class="com.ggli.aop.advice.AroundAdvice"/>

    <bean id="proxy1" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="tutorial2"/>
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
                <value>afterAdvice</value>
                <value>exceptionAdvice</value>
            </list>
        </property>
    </bean>
    <bean id="proxy2" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="tutorial3"/>
        <property name="interceptorNames">
            <list>
                <value>aroundAdvice</value>
            </list>
        </property>
    </bean>
</beans>

单元测试类

import com.ggli.aop.model.Tutorial;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UnitTest {

    @Test
    public void testObject() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Tutorial tutorial = (Tutorial) context.getBean("tutorial1");
        tutorial.printName();
        System.out.println("------------------------------");
        tutorial.printUrl();
        System.out.println("------------------------------");

        try {
            tutorial.printThrowException();
        } catch (Exception e) {

        }
    }

    @Test
    public void testAdvice() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Tutorial tutorial = (Tutorial) context.getBean("proxy1");
        tutorial.printName();
        System.out.println("------------------------------");
        tutorial.printUrl();

        try {
            tutorial.printThrowException();
        } catch (Exception e) {

        }
    }

    @Test
    public void testAround() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Tutorial tutorial = (Tutorial) context.getBean("proxy2");
        tutorial.printName();
        System.out.println("------------------------------");
        tutorial.printUrl();

        try {
            tutorial.printThrowException();
        } catch (Exception e) {

        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值