Spring入门(一站式框架)
- Spring的两大核心
(1)IOC(控制反转)
创建类的对象时,不需要使用原始的方式new对象,IOC是通过配置文件的方式创建对象,把对象的创建交给spring配置文件来完成
(2)AOP(面向切面编程)
不通过修改源代码方式实现功能扩展,拦截器是aop的思想,且采取横向抽取机制取代了传统的纵向继承体系重复性代码。
AOP的操作术语:
配置文件
<aop:config>
<!-- 设置切入点 -->
<aop:pointcut expression="execution(* cm.bean.User.add(..))" id="p1"/>
<!-- 切入面设置 -->
<aop:aspect ref="myUser">
<!-- 前置增强 -->
<aop:before method="before" pointcut-ref="p1"/>
<!-- 异常增强 -->
<aop:after-throwing method="errorAdd" pointcut-ref="p1"/>
<!-- 后置增强 -->
<aop:after-returning method="after" pointcut-ref="p1"/>
<!-- 环绕增强 -->
<aop:around method="around" pointcut-ref="p1"/>
<!-- 最终增强 -->
<aop:after method="finallyAdd" pointcut-ref="p1"/>
</aop:aspect>
</aop:config>
<aop:config>
<aop:pointcut expression="execution(* sh*(..))" id="s1"/>
<aop:aspect ref="myUser">
<aop:around method="shAdd" pointcut-ref="s1"/>
</aop:aspect>
</aop:config>
<aop:config>
<aop:pointcut expression="execution(* cm.bean.Person+.*(..))" id="s2"/>
<aop:aspect ref="myUser">
<aop:before method="eat" pointcut-ref="s2"/>
</aop:aspect>
</aop:config>
User类
package cm.bean;
public class User {
public void add() {
System.out.println("User类的add方法。。。。。。。。。。。");
}
public void show() {
System.out.println("我是user类的show方法,我本身就很强,用不着你们给我加强。");
}
}
MyUser类
package cm.bean;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyUser {
public void before() {
System.out.println("前置增强。。。。。。");
}
public void after() {
System.out.println("后置增强。。。。。。");
}
public void around(ProceedingJoinPoint p) {
System.out.println("环绕前置增强。。。。。。");
try {
p.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("环绕后置增强。。。。。。");
}
public void errorAdd() {
System.out.println(1/0);
System.out.println("在运行过程中发生了未知的异常。。。。。。");
}
public void finallyAdd() {
System.out.println("必须要执行。。。。。。");
}
public void shAdd(ProceedingJoinPoint p) {
System.out.println("前置给以sh开头的方法增强");
try {
p.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("后置给以sh开头的方法增强");
}
public void eat() {
System.out.println("先吃碗刀削面");
}
}
测试类
@Test
public void testAop() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("app.xml");
User bean = context.getBean("user",User.class);
bean.add();
System.out.println("--------------------");
bean.show();
}
效果
使用注释的方法
1 使用注解方式实现aop操作
第一步 创建对象
<bean id="myUser" class="com.edu.xiaoniu.bean.MyUser"></bean>
<bean id="user " class="com.edu.xiaoniu.bean.User"></bean>
第二步 在spring核心配置文件中,开启aop操作
(1)引入约束
(2)开启aop自动代理
第三步 在增强类上面使用注解完成aop操作
(1)在增强类上面使用@Aspect注解
(2)在增强方法上面配置不同类型通知
/*
* 增强类
*/
@Aspect
public class MyUser {
//让这个方法在add方法之前执行,前置通知
@Before(value="execution(* cn.itcast.aop.User.add(..))")
public void before1() {
System.out.println("前置通知................");
}
//后置通知
@AfterReturning(value="execution(* cn.itcast.aop.User.update(..))")
public void after1() {
System.out.println("后置通知....................");
}
//环绕通知
//之前和之后都执行
@Around(value="execution(* cn.itcast.aop.User.delete(..))")
public void around1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知之前................");
//这个方法里面获取被增强的方法,让执行
proceedingJoinPoint.proceed();
System.out.println("环绕通知之后................");
}
//异常通知
@AfterThrowing(value="execution(* cn.itcast.aop.User.find(..))")
public void throw1() {
System.out.println("异常通知.......................");
}
//最终通知
@After(value="execution(* cn.itcast.aop.User.find(..))")
public void finally1() {
System.out.println("最终通知.......................");
}
}
2 配置切入点注解
(1)在增强类里面创建方法,使用注解配置切入点
(2)在增强的方法中使用切入点
2. Spring的bean管理(xml方式)
(1)spring的bean管理的两种方式
基于xml配置文件方式
基于注解的方式
(2)bean创建对象的三种方式
第一种:使用类的无参构造创建对象
class中是类的全类名
第二种:使用静态工厂创建对象
创建静态方法,返回对象
第三种:使用实例工厂创建对象
创建不是静态的方法,返回类对象
(3)bean标签的常用属性
1 id属性
(1)根据id属性值获取对象
(2)在一个spring配置文件中,可以有多个bean标签,但是bean标签id属性值不同
2 class属性
(1)类的全路径
3 name属性
(1)name属性作用和id属性一样的
(2)id属性值里面不能包含特殊符号的
(3)name属性值可以包含特殊符号 /user
4 scope属性
(1)主要作用:配置创建对象是单实例还是多实例对象
(2)属性值:
* 默认值,singleton,表示单实例对象
*prototype,表示多实例对象
** action是多实例对象
request:把创建对象放到request里面
session:把创建对象放到session里面
globalSession:把创建对象放到globalSession里面
(4)bean的属性注入
第一种:使用有参数构造注入
1 创建类,定义属性,生成有参数构造
/**
* 有参数构造注入
* @author asus
*
*/
public class Book {
private String bname;
private String author;
//生成有参数构造
public Book(String bname, String author) {
this.bname = bname;
this.author = author;
}
public void add() {
System.out.println("book:"+bname+"::"+author);
}
}
2 配置属性注入
<!-- 使用有参数构造注入 -->
<bean id="book" class="cn.itcast.attr.Book">
<!-- 体现有参数构造
name: 属性名称
value:设置值
-->
<constructor-arg name="bname" value="易筋经"></constructor-arg>
<constructor-arg name="author" value="小王"></constructor-arg>
</bean>
第二种:使用set方法注入
(1)简单类型注入
1 创建类,定义属性,生成属性set方法
/**
* set方法注入
* @author asus
*
*/
public class Orders {
private String oname;
private String oaddress;
//生成set方法
public void setOname(String oname) {
this.oname = oname;
}
public void setOaddress(String oaddress) {
this.oaddress = oaddress;
}
public void add() {
System.out.println("orders:"+oname+"::"+oaddress);
}
}
2 配置属性注入
<!-- set方法注入 -->
<bean id="orders" class="cn.itcast.attr.Orders">
<!-- name: 属性名称
value:设置值 -->
<property name="oname" value="洗髓经"></property>
<property name="oaddress" value="嵩山"></property>
</bean>
(2)复杂类型注入
1 数组
2 List集合
3 Map集合
4 Properties
/**
* 复杂类型属性
* @author asus
*
*/
public class Customer {
//定义属性
private String[] arrs;
private List<String> list;
private Map<String,String> map;
private Properties properties;
//set方法
public void setArrs(String[] arrs) {
this.arrs = arrs;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void find() {
System.out.println("arrs: "+Arrays.toString(arrs));
System.out.println("list: "+list);
System.out.println("map: "+map);
System.out.println("properties: "+properties);
}
}
<bean id="customer" class="cn.itcast.attr.Customer">
<!-- 数组 -->
<property name="arrs">
<list>
<value>lucy</value>
<value>mary</value>
<value>jack</value>
</list>
</property>
<!-- list -->
<property name="list">
<list>
<value>小王</value>
<value>小金</value>
<value>小奥</value>
</list>
</property>
<!-- map-->
<property name="map">
<map>
<entry key="football" value="足球"></entry>
<entry key="basketball" value="篮球"></entry>
</map>
</property>
<!-- properties -->
<property name="properties">
<props>
<prop key="driverClass">com.mysql.jdbc.Driver</prop>
<prop key="jdbcUrl">jdbc:mysql:///day01</prop>
</props>
</property>
</bean>
第三种:注入对象类型属性
第一步 在service定义dao类型属性
public class UserService {
//目的:在service获取dao对象
//把dao对象注入到service
//1 定义UserDao类型属性
private UserDao userDao;
//2 生成set方法
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
第二步 实现配置
<!-- 注入对象类型属性 -->
<bean id="userDaoImpl" class="cn.itcast.attr.UserDao"></bean>
<bean id="userService" class="cn.itcast.attr.UserService">
//如果注入普通类型属性 使用value属性 ,如果注入对象类型属性,使用ref属性
//name: 类里面的属性名称
//ref:dao对象所在标签id值
<property name="userDao" ref="userDaoImpl"></property>
</bean>
第四种:P名称空间注入
1 引入p名称空间
2 配置文件中,使用名称空间注入属性
(1)spring2.x以下版本,不能使用p名称空间注入
第五种:SpEL注入
写法: #{值}
(1)如果使用spring3.x以下版本,不能使用