Spring入门

spring

@(JAVAWEB)

介绍(基于spring 4.2.4)
对象的容器,spring负责管理项目中的所有对象,可以看成是整个项目的管家
spring是一站式的框架
正因为是容器,容器中装了狠多对象比如web操作的对象,service的对象,dao的对象

spring搭建

  • 1.导包

这几个包,是spring的核心包(core)

Spring入门_第1张图片
image.png

导包之后并没有完成需要 创建xml文件
一般命名为applicationContext.xml

Spring入门_第2张图片
image.png

然后需要添加xml约束

Spring入门_第3张图片
添加xml约束.png

接下来是将类放入Spring的容器中

-新建User类

    @Component("user")
    //相当于xml文件中的an配置
    //最好用下面几种方式
    //@Service("user")
    //@Controller("user")
    //@Repository("user")
    //@Scope(scopeName = "prototy")//此属性来设置user类是否是单例还是多例默认单例。
    public class User {
    @Value("vv")//也可以添加到set方法上,在属性上面是通过反射的field进行赋值,而方法上是通过set方法赋值
    private String name;
    private int age;
    @Autowired //自动装配,前提是car类需要进行component等注解。
    //Autowired会有一问题当spring容器中有多个car类型的对象时,如car1,car2时可以使用下面两种注解
    //@Qualifier("car2") 不推荐此种需要和Autowired一起配合使用
    //@Resource(name = "car2")建议这种方式,当容器中有多个引用对象的时候
    private Car car;


    public User() {
        System.out.println("空参构造");
    }

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", car=" + car +
                '}';
    }

    @PostConstruct //在对象创建之后调用等同于 init-method
    public void init() {
        System.out.println("我是初始化方法");
    }

    @PreDestroy //在销毁前调用
    public void destroy() {
        System.out.println("我是销毁方法");
    }
}

2.到applicationContext.xml中配置

Spring入门_第4张图片
xml添加约束

IDEA会自己生成Spring得约束XML文件


代码测试

Spring入门_第5张图片
代码测试.png

测试结果

Spring入门_第6张图片
测试结果.png

spring概念

IOC (Inverse Of Control) 概念:

将我们创建对象的方式反转,一千对象的创建由我们开发人员自己维护,包括依赖关系也是自己注入.

使用了Spring之后,对象的创建和依赖关系可以由Spring完成创建以及注入.
简单来说就是:反转了对象的创建方式,有自己创建变为了程序控制.

DI(dependency Injection):实现IOC思想需要DI支持

注入方式:

  • 1.set方式
  • 2.构造方法注入
  • 3.字段注入

注入类型:

  • 值类型注入:基本数据类型
  • 引用类型注入:将依赖对象注入

applicationContext和anfactory

BeanFactory
Spring原始接口的实现类功能单一
anFactory接口实现类的容器,特点是每次在获得对象时才会创建对象。
applicationContext
特点:每次容器启动时就会创建容器中配置的所有对象。
提供了更多功能。
从类路劲下加载配置文件:classPathXMLApplicationContext
从硬盘绝对路劲下加载配置文件FilePathXMLApplicationContext
web开发中使用applicationContext,在资源匮乏的环境可以使用anFactory。

spring配置详解

Bean元素

Spring入门_第7张图片
Bean元素.png

Spring创建对象方式
1.空参构造方式
静态工厂方式
动态工厂方式
an元素晋级
scope属性
singleton(默认)单例对像,spring容器中只会存在一个实例
prototype(多例):每次获得时都会创建对象。和struts2使用时必须配置为多例。
request:web环境下对象鱼request对象生命周期一样
session:web环境下雨session声明周期一致
生命周期属性:配置一个方法作为声明周期初始化方法。spring会在对象创建之后首先调用
配置一个而方法作为生命周期的销毁方法,spring会在结束前调用该方法。
spring的分模块化配置

Spring属性注入:set方法
在user中添加car属性

Spring入门_第8张图片
在user中添加car属性.png

加上car对象

Spring入门_第9张图片
加上car对象.png

两个都要重写toStirng方法

目录结构
xml中配置

Spring入门_第10张图片
xml中配置.png

测试代码

测试代码.png

测试结果

Spring入门_第11张图片
测试结果.png

构造函数注入

Spring入门_第12张图片
构造函数注入.png
Spring入门_第13张图片
构造函数注入.png

或者

Spring入门_第14张图片
image.png

p名称空间注入

Spring入门_第15张图片
p名称空间注入.png

spel注入

Spring入门_第16张图片
spel注入.png

复杂类型注入(了解)

用注解配置xml
在原来的lib上添加

Spring入门_第17张图片
在原来的lib上添加.png

步骤
1.为主配置文件引入新的命名空间(约束)
通添加xml约束一样。
2.开启注解配置文件

Spring入门_第18张图片
image.png.png

3.在类中使用注解。
1)类注解

Spring入门_第19张图片
类注解.png

2)值注入

值注入.png

3)引用类型注入

Spring入门_第20张图片
引用类型注入.png

4)初始化、销毁注入

Spring入门_第21张图片
初始化、销毁注入.png

spring与junit整合
首先导包

Spring入门_第22张图片
导包.png
Spring入门_第23张图片
测试.png

spring中的AOP

思想:横向重复,纵向抽取。
对目标对象中的方法进行增强.
具体还清楚

spring中的aop原理

动态代理(优先)

被代理的对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理及技术

cglib

第三方代理技术,cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理,如果目标对象呗final修饰,那么该类无法被cglib代理。

aop名词
joinpoint(连接点):目表对象中,所有增强的方法。
pointcut(切入点):目标对象中,已经增强的方法。
advice(通知/增强):增强的代码。
Target(目标对象):被代理对象,代码中的UserSevviceImpl
Weaving(织入):将通知应用到切入的点的过程
Proxy:将通知织入大目标对象后,形成代理对象。
aspect(切面):切入点+通知。

Spring中的aop演示

1.导包4+2+2+2:

Spring入门_第24张图片
导包.png

2.准备目标对象

/**
 * Created by Bove_shu on 2017/6/9.
 */
public class UserServiceImp implements UserService {
    @Override
    public void save() {

        System.out.println("保存用户");

    }

    @Override
    public void delete() {
        System.out.println("删除用户");
    }

    @Override
    public void update() {
        System.out.println("更新用户");
    }

    @Override
    public void find() {
        System.out.println("查找用户");
    }
}

3.准备通知

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 通知类
 * Created by Bove_shu on 2017/6/9.
 */
public class MyAdvice {

    //前置通知
    //  |-目标方法运行之前调用
    //后置通知(如果出现异常不会调用)
    //  |-在目标方法运行之后调用
    //环绕通知
    //  |-在目标方法之前之后都调用
    //异常拦截通知
    //  |-如果出现异常,就会调用
    //后置通知
    //  |-目标方法调用之后


    //前置通知
    public void fore() {
        System.out.println("这是前置通知");
    }

    //后置通知
    public void afterReturning() {
        System.out.println("这是后置通知(如果出现异常不会调用)");
    }

    //环绕通知
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("这是环绕前置通知");
        Object proceed = pjp.proceed();//调用目标方法
        System.out.println("这是环绕后置通知(如果出现异常不会调用)");
        return proceed;
    }

    //异常通知
    public void afterException() {
        System.out.println("出事啦!");
    }

    //后置通知
    public void after() {
        System.out.println("这是后置通知出现异常也会调用");
    }

}

4.配置进行织入,将通知织入目标对象。

Spring中的Aop配置(xml配置)



    
    
    

    
    
    
    
    
        
        
        
        
            
            
            
            
            
            
        
    

Spring中的Aop配置(注解配置)

前两步步和上面一样

  1. 准备通知对象
 /**
 * 通知类
 * Created by Bove_shu on 2017/6/9.
 */
@Aspect
//标识该类是通知类
public class MyAdvice {

    //前置通知
    //  |-目标方法运行之前调用
    //后置通知(如果出现异常不会调用)
    //  |-在目标方法运行之后调用
    //环绕通知
    //  |-在目标方法之前之后都调用
    //异常拦截通知
    //  |-如果出现异常,就会调用
    //后置通知
    //  |-目标方法调用之后
@Pointcut("execution(* Service..*ServiceImp.*(..))")
public void pc(){

}
    //前置通知
    @fore("MyAdvice.pc())")
    public void fore() {
        System.out.println("这是前置通知");
    }

    //后置通知
    @AfterReturning("MyAdvice.pc())")
    public void afterReturning() {
        System.out.println("这是后置通知(如果出现异常不会调用)");
    }

    //环绕通知
    @Around("MyAdvice.pc())")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("这是环绕前置通知");
        Object proceed = pjp.proceed();//调用目标方法
        System.out.println("这是环绕后置通知(如果出现异常不会调用)");
        return proceed;
    }

    //异常通知
    @AfterThrowing("MyAdvice.pc())")
    public void afterException() {
        System.out.println("出事啦!");
    }

    //后置通知
    @After("MyAdvice.pc())")
    public void after() {
        System.out.println("这是后置通知出现异常也会调用");
    }

}
  1. 将通知织入目标对象


    
    
    

    
    
    
    
    

Spring整合JDBC

spring中提供了一个可以操作数据库的对象,对象封装了JDBC技术.
JDBCTemplate JDBC模板

  1. 准备工作(4+2)
  2. Spring-test包+spring-aop包 jdbc驱动 连接池c3p0 spring-jdbc spring-tx(事务)
  3. jdbc驱动 连接池c3p0
Spring入门_第25张图片
准备工作.png

代码(没用用spring配置的代码):

  1. 需要一个springJDBC模板(该类是接口)定义该类的方法
/**
 * Created by Bove_shu on 2017/6/11.
 */
public interface UserDao {
    //增
    void save(TUser user);

    // 删

    void update(TUser user);
    // 改
    void delete(int id);


    TUser getById(int id);

    // 查
    int getTotalCount();

    //查
    List getAll();
}

2.模板的实现类.具体些数据库操作.

/**
 * Created by Bove_shu on 2017/6/11.
 */
public class UserDaoImpl implements UserDao {
    private JdbcTemplate jt;

    public JdbcTemplate getJt() {
        return jt;
    }

    public void setJt(JdbcTemplate jt) {
        this.jt = jt;
    }

    @Override
    public void save(TUser user) {
        String sql = "insert into t_user values(null,?)";
        jt.update(sql, user.getName());
    }

    @Override
    public void update(TUser user) {
        String sql = "UPDATE  t_user SET NAME =? WHERE id=?";
        jt.update(sql, user.getName(), user.getId());
    }

    @Override
    public void delete(int id) {
        String sql = "delete from t_user where id=?";
        jt.update(sql, id);
    }

    @Override
    public TUser getById(int id) {
        String sql = "SELECT  * from t_user where id=?";
        //这里使用new RowMapper来进行查找  第一个参数resultSet是查询结果的集合,从set中抽取结果放入TUser类中
        //                                        第二个参数是方法调用了几次,就是几.
        jt.queryForObject(sql, (resultSet, i) -> {
            TUser u = new TUser();
            u.setId(resultSet.getInt("id"));
            u.setName(resultSet.getString("name"));
            return u;
        }, id);
        return null;

    }

    @Override
    public int getTotalCount() {
        String sql = "SELECT  count(*) from t_user where id=?";
//        返回个数就用下面的这行代码
        Integer count = jt.queryForObject(sql, Integer.class);
        return count;
    }

    @Override
    public List getAll() {
        String sql = "SELECT  * from t_user ";
        //放回集合是下面的代码,这不需要list.add的方法,你只需要做对Tuser的赋值即可.
        List list = jt.query(sql, new RowMapper() {
            @Override
            public TUser mapRow(ResultSet resultSet, int i) throws SQLException {
                TUser u = new TUser();
                u.setId(resultSet.getInt("id"));
                u.setName(resultSet.getString("name"));
                return u;
            }
        });
        return list;
    }
}
  1. 测试代码
 @Test
    public void test() throws PropertyVetoException {
        //准备连接池
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc,Driver");
        dataSource.setJdbcUrl("jdbc:mysql:///spring-jdbc");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        //1 创建JDBC模板对象
        JdbcTemplate jt = new JdbcTemplate();
        jt.setDataSource(dataSource);
        //2书写sql执行
        String sql="insert into t_user values(null,'vv')";
        jt.update(sql);
    }

使用spring配置写代码

  1. 首先要将用到的类放到容器中,从最底层的开始放入容器中(那个类是最底层可以参考上面的测试代码)


    
    

    
    
        
        
        
        
    
    
    
        
    
    
        
            
        


  1. dao的实现类不变(模板的实现类不变)

  2. 使用sping测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class jdbcTest {
    @Autowired
    UserDao userDao;
    @Test
    public void test() throws PropertyVetoException {
        //准备连接池
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc,Driver");
        dataSource.setJdbcUrl("jdbc:mysql:///spring-jdbc");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        //1 创建JDBC模板对象
        JdbcTemplate jt = new JdbcTemplate();
        jt.setDataSource(dataSource);
        //2书写sql执行
        String sql="insert into t_user values(null,'vv')";
        jt.update(sql);
    }
    @Test
    public void save() throws PropertyVetoException {
        TUser u=new TUser();
        u.setName("bove");
        userDao.save(u);
    }
    @Test
    public void update() throws PropertyVetoException {
        TUser u=new TUser();
        u.setName("bove");
        u.setId(2);
        userDao.update(u);
    }
}

另一种方式
继承JDBCDaoSupport
我只写了一种方式其他方法我就不完善了. 之前的jt用getJdbcTemplate()代替 ,
并且容器中也不需要再配置.
xml配置


    
    

    
    
        
        
        
        
    
    
    
        
    
    
        
            
            
        


代码

public class UserDao2 extends JdbcDaoSupport implements UserDao {
    
    @Override
    public void save(TUser user) {
        String sql = "insert into t_user values(null,?)";
        //这里
        getJdbcTemplate().update(sql, user.getName());
    }

    @Override
    public void update(TUser user) {

    }

    @Override
    public void delete(int id) {

    }

    @Override
    public TUser getById(int id) {
        return null;
    }

    @Override
    public int getTotalCount() {
        return 0;
    }

    @Override
    public List getAll() {
        return null;
    }


}

Spring中的事务

事务:要么成功要么失败.
事务特性:acid(原子性,一致性,持久性,隔离性)

事务的并发问题:脏读,幻读,不可重复读.
事务的隔离级别:
1读未提交
2读已提交
4可重复度
8串行化

spring封装了事务管理代码

事务操作

打开事务
提交事务
回滚事务
事务操作

事务操作对象
因为在不同平台,操作事务的代码各不相同,springs提供了一个接口.
PlatformTransactionManager接口,这个接口是spring中最重要的对象
JDBCTransactionManager
HirbateTransactionManager

spring管理事务的属性介绍
事务的隔离级别
是否只读
事务的传播行为
事务传播行为

Spring入门_第26张图片
事务传播行为.png

spring管理事务的方式
编码式(不推荐)
1.蒋核心事务管理器配置到容器中


    
    

    
    
        
    
    
    
        
    


    
    
        
        
        
        
    
    
    
        
    
    
        
        
    

2.代码中使用

public class AccountServiceImpl implements AccountService {

    private AccountDao dao;
    private TransactionTemplate tt;

    public void setTt(TransactionTemplate tt) {
        this.tt = tt;
    }

    public AccountDao getDao() {
        return dao;
    }

    public void setDao(AccountDao dao) {
        this.dao = dao;
    }

    @Override
    public void transfer(int from, int to, double money) {
        tt.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                //捡钱
                dao.decreaseMoney(from, money);
                //加钱
                dao.increaseMoney(to, money);
            }
        });

    }
}

aopxml配置
准备工作导包
导入新的约束
配置通知
xml配置



    
    

    
    
        
    
    
    
        
    

    
        
            
            
            
            
            
        
    

    
    
        
        

    
    
    
        
        
        
        
    

    
        
    
    
        
        
    

当需要开启事务的方法有很多的时候,可以用下面的方法进行

Spring入门_第27张图片
image.png

*表示通配符

注解配置
准备工作导包
导入新的约束
开启注解管理事务
首先需要到xml中配置



    
    

    
    
    
    
    
    
    
    

   
    主要是这行
    
    
    
        
        
        
        
    

    
        
    
    
        
        
    

代码层

//代表类中的所有方法都采用此事务,当个别不一样的时候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = false)
public class AccountServiceImpl implements AccountService {

    private AccountDao dao;
    private TransactionTemplate tt;

    public void setTt(TransactionTemplate tt) {
        this.tt = tt;
    }

    public AccountDao getDao() {
        return dao;
    }

    public void setDao(AccountDao dao) {
        this.dao = dao;
    }

//    @Override
//    public void transfer(int from, int to, double money) {
//        tt.execute(new TransactionCallbackWithoutResult() {
//            @Override
//            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//                //捡钱
//                dao.decreaseMoney(from, money);
//                //加钱
//                dao.increaseMoney(to, money);
//            }
//        });
//
//    }
    @Override
    //个别不一样的时候在方法上面加此注解就行了
    @Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = true)
    public void transfer(int from, int to, double money) {

                //捡钱
                dao.decreaseMoney(from, money);
                int a=1/0;
                //加钱
                dao.increaseMoney(to, money);
    }
}

当前的事务管理用到的类

目录结构

Spring入门_第28张图片
目录结构.png

AccountDao类

public interface AccountDao {
    //价钱
    void increaseMoney(int id,Double money);
    //捡钱
    void decreaseMoney(int id,Double money);
}

AccountDaoimpl类

public class AccountDaoimpl extends JdbcDaoSupport implements AccountDao {
    @Override
    public void increaseMoney(int id, Double money) {
        getJdbcTemplate().update("UPDATE t_account SET  money=money+? WHERE id=?",money,id);
    }

    @Override
    public void decreaseMoney(int id, Double money) {
        getJdbcTemplate().update("UPDATE t_account SET  money=money-? WHERE id=?",money,id);
    }
}

AccountService类

public interface AccountService {
    //转账方法
    void transfer(int from,int to,double money);
}

AccountServiceImpl类

//代表类中的所有方法都采用此事务,当个别不一样的时候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = false)
public class AccountServiceImpl implements AccountService {

    private AccountDao dao;
    private TransactionTemplate tt;

    public void setTt(TransactionTemplate tt) {
        this.tt = tt;
    }

    public AccountDao getDao() {
        return dao;
    }

    public void setDao(AccountDao dao) {
        this.dao = dao;
    }

//    @Override
//    public void transfer(int from, int to, double money) {
//        tt.execute(new TransactionCallbackWithoutResult() {
//            @Override
//            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//                //捡钱
//                dao.decreaseMoney(from, money);
//                //加钱
//                dao.increaseMoney(to, money);
//            }
//        });
//
//    }
    @Override
    //个别不一样的时候在方法上面加此注解就行了
    @Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = true)
    public void transfer(int from, int to, double money) {

                //捡钱
                dao.decreaseMoney(from, money);
                int a=1/0;
                //加钱
                dao.increaseMoney(to, money);
    }
}

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test {
    @Autowired
    private AccountService as;
    @org.junit.Test
    public void test(){
        as.transfer(1,2,200);
    }
}

end

你可能感兴趣的:(Spring入门)