Spring项目入门须知

快速起步

1. 下载依赖包

  1. spring-beans-5.2.2.RELEASE.jar:包含管理Bean和配置文件的基本功能
  2. spring-core-5.2.2.RELEASE.jar:spring核心包
  3. spring-context-5.2.2.RELEASE.jar:核心扩展包,包含大量工具类
  4. spring-expression-5.2.2.RELEASE.jar:表达式解析语言,支持动态的解析表达式给对象赋值等功能
  5. commons-logging-1.2.jar:日志支持包
  6. log4j-1.2.17.jar:日志支持包

2. 创建Spring项目

  1. 创建Web项目
  2. 将下载好的JAR文件复制到WebRoot/WEB-INF/lib目录下
  3. 创建resources资源目录,并将 log4j.properties 配置文件拷贝其中
  4. 创建 test 测试目录

3. 创建JavaBean

创建 beans.HelloSpring

package beans;

public class HelloSpring {
    private String who = null;
    public String getWho() {return who;}
    public void setWho(String who) {this.who = who;}

    public void print(){
        System.out.println("Hello, " + this.getWho() +" ! ");
    }
}

4. 创建核心配置文件

resources源码目录中创建核心配置文件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-3.2.xsd">

    <!-- 通过bean元素声明需要Spring创建的实例。该实例的类型通过class属性指定,并通过id属性为该实例指定一个名称,以便在程序中使用 -->
    <bean id="helloSpring" class="beans.HelloSpring">
        <!-- property元素用来为实例的属性赋值,此处实际是调用setWho()方法实现赋值操作 -->
        <property name="who">
            <!-- 此处将字符串"Spring"赋值给who属性 -->
            <value>Spring</value>
        </property>
    </bean>
</beans>

5. 编写测试类

test 目录中,创建单元测试类test.SpringTest

package test;

import beans.HelloSpring;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {
    @Test
    public void test() {
        // 实例化Spring的上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取bean的实例
        HelloSpring helloSpring = (HelloSpring) context.getBean("helloSpring");
        // 执行print()方法
        helloSpring.print();
    }
}

Ioc依赖注入

配置文件实现

注入字面量

value标签

<bean id="helloSpring" class="beans.HelloSpring">
    <property name="who">
        <value>Spring</value>
    </property>
</bean>

value属性

<bean id="helloSpring" class="beans.HelloSpring">
    <property name="who" value="value" />
</bean>

P命名空间

<?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.2.xsd">

 <bean id="helloSpring" class="beans.HelloSpring" p:who="Spring"/>

</beans>

注入对象

内部bean

<bean id="a" class="beans.A">
    <property name="b">
        <bean class="beans.B">
            <property name="str" value="val"></property>
        </bean>
    </property>
</bean>

ref属性

<bean id="b" class="beans.B">
    <property name="str" value="val"></property>
</bean>
<bean id="a" class="beans.A">
    <property name="b" ref="b"></property>
</bean>

ref标签

<bean id="b" class="beans.B">
    <property name="str" value="val"></property>
</bean>
<bean id="a" class="beans.A">
    <property name="b">
        <ref bean="b"/>
    </property>
</bean>

P命名空间

<beans xmlns:p="http://www.springframework.org/schema/p" ...>
    <bean id="b" class="beans.B" p:str="val"/>
    <bean id="a" class="beans.A" p:b-ref="b"/>
</beans>

构造注入

构造方法

public A(String strAttr,int intAttr,B b){
  // ...
}

参数索引

<bean id="b" class="beans.B" p:str="val"/>
<bean id="printer" class="beans.Printer">
    <constructor-arg index="0" value="strValue"/>
    <constructor-arg index="1" value="10"/>
    <constructor-arg index="2" ref="b"/>
</bean>

参数名称

<bean id="b" class="beans.B" p:str="val"/>
<bean id="printer" class="beans.Printer">
    <constructor-arg name="strAttr" value="strValue"/>
    <constructor-arg name="intAttr" value="10"/>
    <constructor-arg name="b" ref="b"/>
</bean>

注入null值

<bean id="id" class="package.class">
    <property name="attr"><null></null></property>
</bean>

注入空字符串

<bean id="id" class="package.class">
    <property name="attr"><value></value></property>
</bean>

注入包含特殊字符的值

CDATA

<bean id="id" class="package.class">
    <property name="attr"><value><![CDATA[P&G]]></value></property>
</bean>

实体符号

<bean id="printer" class="beans.Printer">
    <property name="ink"><value>P&amp;G</value></property>
</bean>

注入List集合

<bean id="id" class="package.class">
    <property name="lists">
        <list>
            <value>黑色</value>
            <value>彩色</value>
        </list>
    </property>
</bean>

注入Set集合

<bean id="id" class="package.class">
    <property name="sets">
        <set>
            <value>黑色</value>
            <value>彩色</value>
        </set>
    </property>
</bean>

注入Map集合

<bean id="id" class="package.class">
    <property name="maps">
        <map>
            <entry>
                <key><value>k1</value></key>
                <value>v1</value>
            </entry>
            <entry>
                <key><value>k2</value></key>
                <value>v2</value>
            </entry>
        </map>
    </property>
</bean>

注入Properties集合

<bean id="id" class="package.class">
    <property name="prop">
        <props>
            <prop key="k1">v1</prop>
            <prop key="k2">v2</prop>
        </props>
    </property>
</bean>

注解实现Ioc

全局配置

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-2.0.xsd">
    <!-- 扫描包中注解标注的类 -->
   <context:component-scan base-package="beans"/>
</beans>

定义Bean

定义普通Bean

@Component
public class BeanName { /* ... */ }
// 等效于
@Component("beanName")
public class BeanName { /* ... */ }

定义DAO Bean

@Repository
public class BeanDao { /* ... */ }
// 等效于
@Repository("beanDao")
public class BeanDao { /* ... */ }

定义业务Bean

@Service
public class BeanService { /* ... */ }
// 等效于
@Service("beanService")
public class BeanService { /* ... */ }

定义控制器Bean

@Controller
public class BeanController { /* ... */ }
// 等效于
@Controller("beanController")
public class BeanController { /* ... */ }

装配Bean

以类型装配

@Autowired
private BeanClass bean;

如果有多个类型相同的Bean,则需要指定Bean名称

@Autowired
@Qualifier("beanName")
private BeanClass bean;
// 或
private BeanClass bean;
@Autowired
@Qualifier("beanName")
public void setBean(BeanClass bean) { /* ... */ }
// 或
private BeanClass bean;
@Autowired
public void setBean(@Qualifier("beanName")BeanClass bean) { /* ... */ }

构造方法装配

@Autowired
public Printer(BeanClass bean){/* ... */}
// 或
@Autowired
public Printer(@Qualifier("beanName")BeanClass bean){/* ... */}

阻止Bean组件不存在时报异常

@Autowired(required = false)
private BeanClass bean;

将相同类型的Bean装配到集合

@Autowired
private List<BeanClass> beans;

优先以名称装配,如果没有找到指定的Bean,则以类型装配

// 先找名称为 bean 的 Bean,如果没有找,则找名称为 beanClass 的 Bean,如果还没有找到,则寻找类型为 BeanClass 的 Bean
@Resource
private BeanClass bean;
// 找名称为 beanName 的 Bean
@Resource(name="beanName")
private BeanClass bean;
// 找名称为 bean 的 Bean
private BeanClass bean;
@Resource
public void setBean(BeanClass bean) { /* ... */ }

AOP实现

配置文件实现

1. 下载依赖包

  1. aopalliance-1.0.jar
  2. aspectjweaver-1.6.9.jar
  3. spring-aop-5.2.2.RELEASE.jar

2. 创建被增强类

package aopdemo;
import org.springframework.stereotype.Component;
@Component("a")
public class A {
    public void fun1() { /* ... */ }
    public void fun2() { throw new RuntimeException("fun2 抛出异常"); }
    public void fun3() { /* ... */ }
    public void fun4() { throw new RuntimeException("fun4 抛出异常"); }
}

3. 创建切面

package aopdemo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Component
public class AspectImpl {
    /**
     * 前置增强
     * @param joinPoint 切入点对象
     */
    public void before(JoinPoint joinPoint) {
        System.err.println("正在执行前置增强。。。");
    }
    /**
     * 后置增强
     * @param joinPoint 切入点对象
     * @param result 被增强方法的返回值
     */
    public void afterReturning(JoinPoint joinPoint, Object result) {
        System.err.println("正在执行后置增强,返回值为:" + result);
    }
    /**
     * 异常增强
     * @param joinPoint 切入点对象
     * @param e 被增强方法抛出的异常对象
     */
    public void afterThrowing(JoinPoint joinPoint, RuntimeException e) {
        System.err.println("正在执行异常增强,异常为:" + e);
    }
    /**
     * 最终增强
     * @param joinPoint 切入点对象
     */
    public void after(JoinPoint joinPoint) {
        System.err.println("正在执行最终增强。。。");
    }
    /**
     * 环绕增强
     * @param joinPoint 切入点对象
     * @return 被增强方法的返回值
     */
    public Object around(ProceedingJoinPoint joinPoint) {
        Object result = null;
        try {
            System.err.println("开始执行环绕增强。。。");
            result = joinPoint.proceed();
            System.err.println("结束执行环绕增强。。。");
        } catch (Throwable e) {
            System.err.println("环绕增强的异常处理:" + e);
        } finally {
            return result;
        }
    }
}

4. 全局配置

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <context:component-scan base-package="aopdemo" />
    <aop:config>
        <!-- 切入点 -->
        <aop:pointcut expression="execution(public void fun1())" id="fun1"/>
        <aop:pointcut expression="execution(public void fun2())" id="fun2"/>
        <aop:pointcut expression="execution(public void fun3())" id="fun3"/>
        <aop:pointcut expression="execution(public void fun4())" id="fun4"/>
        <!-- 切面 -->
        <aop:aspect ref="aspectImpl">
            <!-- 前置增强 -->
            <aop:before method="before" pointcut-ref="fun1" />
            <!-- 后置增强 -->
            <aop:after-returning method="afterReturning" pointcut-ref="fun1" returning="result"/>
            <!-- 异常增强 -->
            <aop:after-throwing method="afterThrowing" pointcut-ref="fun2" throwing="e"/>
            <!-- 最终增强 -->
            <aop:after method="after" pointcut-ref="fun3"/>
            <!-- 环绕增强 -->
            <aop:around method="around" pointcut-ref="fun4"/>
        </aop:aspect>
    </aop:config>
</beans>

5. 编写测试类

@Test
public void test() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    A a = (A)context.getBean("a");
    // 依次执行一下方法进行测试
    // a.fun1();
    // a.fun2();
    // a.fun3();
    a.fun4();
}

注解实现AOP

切面实现类

package aopdemo;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AspectImpl {
    // 定义通用切入点
    @Pointcut("execution(public void fun1())")
    public void pointcut1() {}
    // 前置增强
    @Before("pointcut1()")
    public void before(JoinPoint joinPoint) { /* ... */ }
    // 后置增强
    @AfterReturning(pointcut = "pointcut1()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) { /* ... */ }
    // 异常增强
    @AfterThrowing(pointcut = "execution(public void fun2())", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, RuntimeException e) { /* ... */ }
    // 最终增强
    @After("execution(public void fun3())")
    public void after(JoinPoint joinPoint) { /* ... */ }
    // 环绕增强
    @Around("execution(public void fun4())")
    public Object around(ProceedingJoinPoint joinPoint) { /* ... */ }
}

全局配置

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <context:component-scan base-package="aopdemo" />
     <!-- 启用Aspectj,并自动创建代理 -->
    <aop:aspectj-autoproxy/>
</beans>

切入点表达式匹配规则

匹配所有类型的返回值

public * addNewUser(entity.User)

匹配所有方法名

public void *(entity.User)

匹配所有参数个数和类型

public void addNewUser(..)

匹配 com.service 包下所有类的所有方法

* com.service.*.*(..)

匹配 com.service 包及其子包下所有类的所有方法

* com.service..*.*(..)

JoinPoint

获取目标类完全限定名

joinPoint.getTarget()

获取目标方法名

joinPoint.getSignature().getName()

获取目标方法入参数组

joinPoint.getArgs()

ProceedingJoinPoint

获取目标类完全限定名

joinPoint.getTarget()

获取目标方法名

joinPoint.getSignature().getName()

获取目标方法入参数组

joinPoint.getArgs()

执行目标方法并获取返回值

joinPoint.proceed()
posted @ 2021-01-20 11:31  编码小高  阅读(93)  评论(0编辑  收藏  举报