Spring的简单使用
三层架构
三层架构 | 作用 |
---|---|
表现层(Web) | 接收请求,向客户端响应结果 |
业务层(Service) | 负责业务逻辑处理 |
持久层(Dao) | 与数据库交互,对数据库表进行增删改查 |
CRUD
Create 添加数据 ---> insert语句
Read 读取数据 ---> select语句
Update 修改数据 ---> update语句
Delete 删除数据 ---> delete语句
Spring IOC容器
- 配置在 /resources/bean.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">
实体类User
class User{ String name; Integer age; public void init(){}; public void destroy(){}; }
<!--创建User对象: User user = new User();-->
<!--
bean 表示要创建的对象
id 对应的引用名称
class 表示对象的全路径
-->
<bean id="user" class="com.osc.entity.User"/>
</beans>
等价于
User user = new User();
实例化的更多属性
属性 | 说明 |
---|---|
id | 对象的引用名称;唯一性 |
name | 对象的引用名称; 与id区别是:name一次可以定义多个引用名称。 |
class | 类的类路径 |
scope | 设置bean的作用范围。 -------------------------------- singleton:单例。默认值 prototype:多例 request:web项目中,将对象存入request域中 session:web项目中,将对象存入session域中 globalsession:web项目中,应用在集群环境, 如果没有集群,环境,相当于session |
init-method | 指定类中初始化方法的名称,在构造方法执行完毕后立即执行 |
destroy-method | 指定类中销毁方法名称,在销毁spring容器前执行 |
lazy-init | 设置为true表示延迟创建对象,即在第一次使用对象时候才创建单例 的对象,只对单例对象有效。 |
<bean
id="user2"
name="user3,user4"
class="com.osc.entity.User"
scope="prototype"
lazy-init="true"
init-method="init"
destroy-method="destroy"/>
注入值
<!--
注入值
<constructor-arg> : 构造方法的注入
index:参数列表的索引
name:实体类的成员变量名
type:成员变量的类型
value:注入的值
<property> : set方法的注入
id:set变量名的方法
value:注入的值
-->
<bean id="user" class="com.osc.entity.User">
<constructor-arg index="0" name="name"
type="String" value="我是名字"/>
<constructor-arg index="1" name="age"
type="int" value="100"/>
<property name="age" value="168"/>
</bean>
等价于
User user = new User("我是名字",100); user.setAge(168);
bean引用
<bean id="str_name" class="java.lang.String">
<constructor-arg value="Jack"/>
</bean>
<bean id="user" class="com.osc.entity.User">
<property name="name" ref="str_name"/>
</bean>
等价于
String str_name = new String("Jack"); User user = new User(); user.setName(str_name);
Spring IOC创建Druid连接池
利用容器实例对象
利用注解扫描开启实例对象
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url"
value="jdbc:mysql://url/database?characterEncoding=utf8"></property>
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="initialSize" value="3"></property>
<property name="maxActive" value="10"></property>
</bean>
等价于
DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://url/database?characterEncoding=utf8"); dataSource.setUserName("root"); ...
利用容器创建JDBCTemplate对象+Dao+Service
<!--2.创建JdbcTemplate,注入连接池-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--3.创建dao,注入JdbcTemplate对象-->
<bean id="dao" class="com.osc.dao.impl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!--4.创建service,注入dao-->
<bean id="service" class="com.osc.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
等价于
// 2.创建JdbcTemplate,注入连接池 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // 3.创建dao,注入JdbcTemplate对象 AccountDaoImpl dao = new AccountDaoImpl(); dao.setJdbcTemplate(jdbcTemplate); // 4.创建service,注入dao AccountServiceImpl service = new AccountServiceImpl(); service.setAccountDao(dao);
注解开发
@Component
在java类上使用这个注解相当于在bean.xml创建了一个类,默认创建的id是首指母小写的类名
public class OscBean{} --> <bean id="oscBean" class="com.osc.OscBean">...</bean>
@Controller
一般用于表现层的注解。
@Service
一般用于业务层的注解。
@Repository
一般用于持久层的注解。
都是和@Component作用完全一样,只是一个别名便于分别
@Autowired
- 用来注入数据
- 根据@Autowired修饰的字段类型,去容器中找对象注入进来
- 可以省去set方法
- 容器如有多个符合时根据bean的id注入
@Autowired
String name;
<bean id="str" class="java.lang.String">
<constructor-arg value="osc"/>
</bean>
<bean id="name" class="java.lang.String">
<constructor-arg value="zzy"/>
</bean>
例如上述情况:@Autowired类型为String,容器有2个bean符合注入,此时会以id识别注入,找不到就报错
name : "zzy"
开启注解扫描
- 配置在bean.xml
- 开启注解扫描:扫描com.osc.domain包下的注解
- base-package指定要扫描的包下所有的类以及当然包下所有的子包下所有的类,如果要扫描多个包用逗号隔开
<context:component-scan base-package="com.osc.domain"></context:component-scan>
@Bean
- @Bean和@Component的目的都是告知Spring要为这个类创建bean,但是Bean比Component的自定义性更强
- @Bean只能用在方法上,返回的对象会创建到bean容器中
@PropertySource
- 用于加载.properties文件数据
- 加载类路径osc.properties文件
@PropertySource("classpath:osc.properties") class User{}
@Value
依赖于@PropertySource使用,用于取properties文件里的值
osc.properties
name=osc
age=18
@PropertySource("classpath:osc.properties")
class User{
@Value("${name}") //取到osc.properties中键name对应的值
String name; //osc
@Bean
public User createUser(){
User user = new User();
user.setName(name);
return user; //会在容器创建这个User对象,id=user
}
}
AOP切面编程
准备一个实现类或者普通类
public class SerImpl implements IService {
@Override
public void save() {
System.out.println("保存账号!");
}
}
创建一个日志记录类
public class Logger {
public void printLog(){
System.out.println("记录用户操作日志。");
}
}
基于xml的AOP配置
标签名 | 作用 |
---|---|
aop:config | 声明aop配置 |
aop:aspect | 配置切面 |
-id | 给切面取一个唯一标识的名称 |
-ref | 引用日志类bean的id |
aop:pointcut | 配置切入点表达式 |
-id | 给切入点取一个表达式唯一标识的名称 |
-expression | 指定切入点表达式 访问修饰符 返回值 包名称.类名称.方法名称(参数列表) |
aop:before | 配置前置通知 |
-method | 指定通知方法的名称 |
-pointcut-ref | 指定切入点表达式(aop:pointcut)的id |
<!--配置客户service-->
<bean id="serImpl" class="om.osc.SerImpl"></bean>
<!--配置日志通知advice-->
<bean id="logAdvice" class="com.itheima.utils.Logger"></bean>
<aop:config>
<aop:aspect id="logAspect" ref="logAdvice">
<aop:pointcut id="pt"
expression="execution(public void com.osc.SerImpl.save())"> </aop:pointcut>
<aop:before method="printLog" pointcut-ref="pt"></aop:before>
</aop:aspect>
</aop:config>
切入点表达式
- 访问修饰符 返回值 包名称.类名称.方法名称(参数列表)
访问修饰符可以省略
*****:统配一个包名或者类名或者方法名
…:表示当前包及其子包
全匹配方式
public void com.itheima.service.impl.UserServiceImpl.save()
访问修饰符可以省略
public com.itheima.service.impl.UserServiceImpl.save()
包名和修饰符都可以使用* (有多少个包使用多少个*)
* *.*.*.*.UserServiceImpl.save()
包名中使用…,表示当前包及其子包
* com..*.UserServiceImpl.save()
类名和方法名也可以使用*
* com..*.*.save()
* com..*.*.*()
* com..*.*Impl.*av*()
参数列表也可以使用*和…
//参数任意,用*必须带有参数
* com..*.*.save(*)
//参数任意,用..参数可有可无
* com..*.*.save(..)
其他写法
//表示容器中以Service结尾的所有类匹配
bean(*Service)
通知类型
l 前置通知:在目标方法执行前执行
l 后置通知:在目标方法正常返回后执行。它和异常通知只能执行一个
l 异常通知:在目标方法发生异常后执行。它和后置通知只能执行一个
l 最终通知:无论目标方法正常返回,还是发生异常都会执行
l 环绕通知:综合了前面四类通知,可以手动控制通知的执行时间点和顺序
修改日志通知类
public class Logger {
public void beforeNif(){}
public void afterNif(){}
public void throwNif(){}
public void finalNif(){}
}
<aop:config>
<aop:aspect ref="logger">
<!--切入点表达式-->
<aop:pointcut id="pt" expression="execution(* com..*.*(..))"/>
<!--【前置通知】-->
<aop:before method="beforeNif" pointcut-ref="pt"/>
<!--【后置通知】-->
<aop:after-returning method="afterNif" pointcut-ref="pt"/>
<!--【异常通知】-->
<aop:after-throwing method="throwNif" pointcut-ref="pt"/>
<!--【最终通知】-->
<aop:after method="finalNif" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
事务控制
配置均在bean.xml中
创建事务管理器
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 引用jdbc连接数据库的数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
配置事务通知规则
标签/属性 作用 tx:advice 事务通知规则配置 -transaction-manager 引用的事务管理器 tx:attributes 事务应用规则配置 -tx:method 对指定的方法,如何管理事务 -name 表示方法名 -read-only 是否只读,默认false -propagation 默认值表示当前执行的方法必须有事务环境
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--find/query/select/search
开头的方法,都是只读事务,事务传播行为(有事务支持,没有也可以)-->
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="select*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="search*" read-only="true" propagation="SUPPORTS"/>
<!--除了上面的方法,其他的所有方法都是读写事务,传播行为(必须有事务环境)-->
<tx:method name="*" read-only="false" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
AOP配置
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.osc.service.impl.*.*(..))"/>
<!--配置切入点表达式与通知的关联-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
注解开启事务
事务属性
readOnly = false 默认值,读写事务,可以进行CRUD操作
propagation = Propagation.REQUIRED 默认值表示当前执行的方法必须有事务环
<!--4.2 开启Spring声明式事务的注解支持(就可以使用@Transactional注解)-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
@Service
//都是默认值,可以简写为@Transactional
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
public class UserServiceImpl implements IUserService {}