Spring项目入门须知
快速起步
1. 下载依赖包
- spring-beans-5.2.2.RELEASE.jar:包含管理Bean和配置文件的基本功能
- spring-core-5.2.2.RELEASE.jar:spring核心包
- spring-context-5.2.2.RELEASE.jar:核心扩展包,包含大量工具类
- spring-expression-5.2.2.RELEASE.jar:表达式解析语言,支持动态的解析表达式给对象赋值等功能
- commons-logging-1.2.jar:日志支持包
- log4j-1.2.17.jar:日志支持包
2. 创建Spring项目
- 创建Web项目
- 将下载好的JAR文件复制到
WebRoot/WEB-INF/lib
目录下 - 创建
resources
资源目录,并将 log4j.properties 配置文件拷贝其中 - 创建
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&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. 下载依赖包
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()