1.Spring是分层的JavaSE/EE full-stack(一站式) 轻量级开源框架
EE的三层结构:web层、业务层、数据访问层(持久层,集成层)
2.Spring的核心:IOC(控制反转)、AOP(面向切面编程)
3.学习Spring需要的入门准备(①下载Spring开发包 ②创建web工程引入相应的jar包 ③创建Spring配置文件④在配置中配置类⑤创建测试类)
Spring的入门级案例:
1.创建一个接口
package org.llj.springdemo;
public interface HelloService {
public void sayHello();
}
2.创建该接口的实现类
public class HelloServiceImpl implements HelloService {
private String info;
public void setInfo(String info) {
this.info = info;
}
@Override
public void sayHello() {
System.out.println("hello spring"+info);
}
}
3.配置配置文件:
4.编写测试类:
public class ServiceTest {
@Test
//传统方式的测试
public void demo1(){
HelloService helloService=new HelloServiceImpl();
helloService.sayHello();
}
@Test
//采用spring框架测试
public void demo2(){
org.springframework.context.ApplicationContext applicationContext
=new ClassPathXmlApplicationContext("applicationContext.xml");
HelloService helloService=(HelloService) applicationContext.getBean("userService");
helloService.sayHello();
}
@Test
public void demo3(){
org.springframework.context.ApplicationContext applicationContext
=new FileSystemXmlApplicationContext("applicationContext.xml");
HelloService helloService=(HelloService) applicationContext.getBean("userService");
helloService.sayHello();
}
}
4.DI:依赖注入:在Spring创建对象的过程中,把对象依赖的属性注入到类中.
5.IOC装配bean的方式(三种)
①构造方法实例化:
创建要实例化的类
package org.llj.springdemo2;
/**
* 使用无参数的构造方法实例化
* @author lenovo
*
*/
public class bean1 {
}
加载配置文件
编写测试类
@Test
public void demo1(){
//1.加载类
ApplicationContext applicationContext=new ClassPathXmlApplicationContext
("ApplicationContext.xml");
bean1 bean1=(org.llj.springdemo2.bean1) applicationContext.getBean("bean1");
System.out.println(bean1);
}
②静态工厂实例化
package org.llj.springdemo2;
/**
* 使用静态工厂实例化
* @author lenovo
*
*/
public class bean2 {
}
package org.llj.springdemo2;
public class bean2Factory {
public static bean2 getBean2(){
System.out.println("静态工厂实例化");
return new bean2();
}
}
加载配置文件:
测试:
@Test
public void demo2(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext
("ApplicationContext.xml");
bean2 bean2=(org.llj.springdemo2.bean2) applicationContext.getBean("bean2");
System.out.println(bean2);
}
③实例工厂实例化
package org.llj.springdemo2;
/**
* 使用实例工厂的方法实例化
* @author lenovo
*
*/
public class bean3 {
}
package org.llj.springdemo2;
/**
* 使用实例工厂实例化
* @author lenovo
*
*/
public class bean3Factory {
public bean3 getBean3(){
System.out.println("实例工厂实例化");
return new bean3();
}
}
配置文件:
测试:
@Test
public void demo3(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext
("ApplicationContext.xml");
bean3 bean3=(org.llj.springdemo2.bean3) applicationContext.getBean("bean3");
System.out.println(bean3);
}
6.bean中属性注入:
①构造器的方法注入:
②setter方法注入:
property 标签中name就是属性名称,value就是属性值 ref表示引用的其他对象
③名称空间p注入:
④spel写法
value的#号后的大括号如果有单引号,说明是常量;如果没有单引号,说明是引用类型
⑤集合注入
梅
玲
花花
红军
⑥propeties注入:
root
123
7.IOC注解方式装配bean
Spring的框架中提供了与@Component注解等效的三个注解:
@Repository 用于对DAO实现类进行标注
@Service 用于对Service实现类进行标注
@Controller 用于对Controller实现类进行标注
普通属性;
@Value(value="itcast")
private String info;
对象属性:
@Autowired:自动装配默认使用类型注入.
@Autowired
@Qualifier("userDao") --- 按名称进行注入.
@Autowired
@Qualifier("userDao")
private UserDao userDao;
等价于
@Resource(name="userDao")
private UserDao userDao;
8.spring整合JUNIT测试
1.程序中有Junit环境.
2.导入一个jar包.spring与junit整合jar包.
* spring-test-3.2.0.RELEASE.jar
3.测试代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext2.xml")
public class springTest {
@Autowired
private UserService userservice;
@Test
public void demo1(){
userservice.sayhello();
}
}
AOP的底层实现:
1.JDK动态代理
public class JDKProxy implements InvocationHandler{
private UserDao userDao;
public JDKProxy(UserDao userDao) {
super();
this.userDao = userDao;
}
public UserDao createProxy(){
//第一个参数为类装载器,第二个参数是真实类所拥有的接口,第三个数组则是当前类
UserDao proxy=(UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(), this);
return proxy;
}
//调用目标对象的任意一个方法,都相当于调用了Invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
if("add".equals(method.getName())){
//记录日志
System.out.println("日志记录======================");
//执行add方法
Object result=method.invoke(userDao, args);
return result;
}else {
return method.invoke(userDao, args);
}
}
}
2.CGLIB动态代理
public class CGLibProxy implements MethodInterceptor {
private ProductDao productDao;
public CGLibProxy(ProductDao productDao) {
super();
this.productDao = productDao;
}
public ProductDao createProxy(){
//使用CGLib生成代理
//1.创建核心类:Enhancer
Enhancer enhancer=new Enhancer();
//2.为其设置父类
enhancer.setSuperclass(productDao.getClass());
//3.设置回调
enhancer.setCallback(this);
//4.创建代理
return (ProductDao) enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if("add".equals(method.getName())){
System.out.println("日志记录=================");
Object object=methodProxy.invokeSuper(proxy, args);
return object;
}
return methodProxy.invokeSuper(proxy, args);
}
}
Spring框架,如果类实现了接口,就使用JDK的动态代理生成代理对象,如果这个类没有实现任何接口,使用CGLIB生成代理对象.
Spring中AspectJ的支持
AspectJ增强:
@Before 前置通知,相当于BeforeAdvice
@AfterReturning 后置通知,相当于AfterReturningAdvice
@Around 环绕通知,相当于MethodInterceptor
@AfterThrowing抛出通知,相当于ThrowAdvice
@After 最终final通知,不管是否异常,该通知都会执行
@DeclareParents 引介通知,相当于IntroductionInterceptor (不要求掌握)
1.基于注解的
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;
/**
* 切面类,就是切点与增强的结合
* @author lenovo
*
*/
@Aspect
public class MyAspect {
@Before("execution(* org.llj.spring.demo1.UserDao.add(..))")
public void before(JoinPoint joinPoint){
System.out.println("这是一个前置增强……"+joinPoint);
}
@AfterReturning(value="execution(* org.llj.spring.demo1.UserDao.delete(..))",returning="returnVal")
public void after(Object returnVal){
System.out.println("这是一个后置增强……"+returnVal);
}
@Around("MyAspect.mypointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
System.out.println("环绕前增强");
Object obj=proceedingJoinPoint.proceed();
System.out.println("环绕后增强");
return obj;
}
@AfterThrowing(value="MyAspect.mypointcut()",throwing="e")
public void throwing(Throwable e){
System.out.println("不好了。出异常了"+e.getMessage());
}
@After("MyAspect.mypointcut()")
public void after(){
System.out.println("最终通知……");
}
@Pointcut("execution(* org.llj.spring.demo1.UserDao.find(..))")
private void mypointcut(){
}
}
二、基于XML的
package org.llj.spring.demo2;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspectXML {
public void before(){
System.out.println("前置通知……");
}
public void aferReturning(Object returnVal){
System.out.println("后置通知……"+returnVal);
}
//环绕通知
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕前通知……");
Object result=proceedingJoinPoint.proceed();
System.out.println("环绕后通知……");
return result;
}
//异常通知
public void afterThrowing(Throwable e){
System.out.println("出异常了……"+e.getMessage());
}
//最终通知
public void after(){
System.out.println("这是最终通知……");
}
}
Spring的jdbcTemplate
1.jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_day02
jdbc.user=root
jdbc.password=123
2.spring 提供了三种连接池(以下)
①.配置spring默认的连接池
②.配置dbcp连接池
③.-配置c3p0连接池
3.定义jdbcTemplate摸板类
JdbcTemplate的CRUD的操作
import java.awt.List;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
* jdbcDaoSupport这个类中已经定义了模板,并且有一个set方法,所以这边继承JdbcDaoSupport之后就
* 不需要在定义模板
* @author lenovo
*
*/
public class UserDao extends JdbcDaoSupport {
public void add(User user){
String sql="insert into user values(null,? )";
this.getJdbcTemplate().update(sql,user.getName());
}
public void update(User user){
String sql="update user set name = ? where id = ?";
this.getJdbcTemplate().update(sql, user.getName(),user.getId());
}
public void delete(User user){
String sql="delete from user where id = ?";
this.getJdbcTemplate().update(sql, user.getId());
}
public String findNameById(int id){
String sql="select name from user where id = ?";
return this.getJdbcTemplate().queryForObject(sql, String.class, id);
}
public User findById(int id){
String sql="select * from user where id = ?";
User user=(User)this.getJdbcTemplate().queryForObject(sql, new UserRowMapper(),id);
return user;
}
public java.util.List findAll(){
String sql="select * from user";
return this.getJdbcTemplate().query(sql, new UserRowMapper());
}
class UserRowMapper implements RowMapper{
/**
* rs:结果集
* rowNum:行号
*/
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user=new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
return user;
}
}
}
测试方法:
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class springTest {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Test
public void demo1(){
User user=new User();
user.setName("娟儿");
userDao.add(user);
}
@Test
public void demo2(){
User user=new User();
user.setId(1);
user.setName("珑珠");
userDao.update(user);
}
@Test
public void demo3(){
User user=new User();
user.setId(1);
userDao.delete(user);
}
@Test
public void demo4(){
String name=userDao.findNameById(2);
System.out.println(name);
}
@Test
public void demo5(){
User user=userDao.findById(2);
System.out.println(user);
}
@Test
public void demo6(){
List list=userDao.findAll();
for (User user : list) {
System.out.println(user);
}
}
}
1.编程式事务管理(手动编写代码完成事务的管理)
2.声明式事务管理 (不需要手动编写,配置 )
1.需要有相应的数据库。
2.创建一个动态web项目:导入相应的jar;引入配置文件
3.创建类:XXXService;XXXDao
4.在Spring中注册业务层类和持久层类:
5.OK,编写测试类,测试环境是否搭建成功。
不管哪种方式都需要事务管理器(TransactionManager)
一.手动编写的方式完成事务管理
1.注册事务模板:(TransactionTemplate)
2.在业务层注入模板类:(模板管理事务)
3.在业务层代码上使用模板:(以下是我的业务层代码)
package org.llj.spring.demo1;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
private TransactionTemplate transactionTemplate;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Override
public void transfer(final String from, final String to, final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
// TODO Auto-generated method stub
accountDao.out(from, money);
int i=10/0;
accountDao.in(to, money);
}
});
}
}
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
// TODO Auto-generated method stub
accountDao.out(from, money);
int i=10/0;
accountDao.in(to, money);
}
});
}
}
二.原始的声明式事务管理:
1.创建业务层代理对象(飘蓝的为属性设置,如果不写,则系统默认)
PROPAGATION_REQUIRED PROPAGATION_REQUIRED
2.编写测试类(注意注入的是代理对象)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class springTest2 {
@Autowired
@Qualifier("accountServiceProxy")
private AccountService accountService;
@Test
public void demo1(){
accountService.transfer("aaa", "bbb", 100d);
}
}
"accountServiceProxy")
private AccountService accountService;
@Test
public void demo1(){
accountService.transfer("aaa", "bbb", 100d);
}
}
三.声明式事务管理(基于切面)
1.导入所需的jar包,引入配置文件(aop、tx的约束)
2.事务管理(定义增强)
3.定义切点和通知
4.测试(不需要注入代理对象,注入service对象即可)
四.基于注解的事务管理
1.注解事务:
2.在service 上使用注解
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String from, String to, Double money) {
accountDao.out(from, money);
//int i=10/0;
accountDao.in(to, money);
}
}
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String from, String to, Double money) {
accountDao.out(from, money);
//int i=10/0;
accountDao.in(to, money);
}
}
以上为spring中的几种事务管理;其中手动编写的方式代码量大,代码具有入侵性
原始的声明式事务管理需要为每一个管理事务的类生成代理,需要为每个类都进行配置。
基于aspect的声明式事务管理是重点。