Spring总结

Spring 四要点 IOC DI AOP jdbc+事务

IOC (控制反转) 三种

三种方式注册bean xml 注解 java类
https://www.cnblogs.com/wuchanming/p/5426746.html
@Component @Controller @Service @Repository
java类 @Configuration @Bean

DI (依赖注入) 三种

1) xml 自动注入 四种方式:



byName – 根据属性名称自动装配
byType – 按数据类型自动装配
constructor – 在构造函数参数的byType方式。
autodetect – 先constructor 没有用 byType

2) xml 手动注入:

ref 对象 value 值



"" 填写属性名字
 数组或者List集合
  set
  map
 properties

p名称空间的注入 SpEL注入方式 (了解内容)

3) 注解


字段 set方法 构造函数

@Autowired      byType  required
@Qualifer 配合@Autowired 设置为byName
@Resource 设置name 为byName 否则为byType
@PostConstruct    -- 相当于init-method
@PreDestroy       -- 相当于destroy-method
@Scope(value="prototype")  singleton-- 单例,默认值 prototype-- 多例
@Value -- 注入值

参考链接
https://www.cnblogs.com/wuchanming/p/5426746.html

使用

// 使用Spring的工厂:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过工厂获得类:
UserService userService = (UserService) applicationContext.getBean("userService");
userService.sayHello();

spring 整合junit测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo{

    @Resource(name="userService")
    private UserService userService;

    @Test
    public void demo2(){
        userService.save();
    }
}

AOP (面向切面编程) 原理两种 方式两种

Srping框架的AOP技术底层也是采用的代理技术,代理的方式提供了两种

1) 基于JDK的动态代理
* 必须是面向接口的,只有实现了具体接口的类才能生成代理对象

2) 基于CGLIB动态代理
* 对于没有实现了接口的类,也可以产生代理,产生这个类的子类的方式

如果实现类接口,使用JDK动态代理完成AOP
如果没有实现接口,继承了类,采用CGLIB动态代理完成AOP

JDK的动态代理
public class MyProxyUtils {
    public static UserDao getProxy(final UserDao dao) {
        // 使用Proxy类生成代理对象
        UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
                dao.getClass().getInterfaces(), new InvocationHandler() {

                    // 代理对象方法一执行,invoke方法就会执行一次
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if("save".equals(method.getName())){
                            System.out.println("记录日志...");
                            // 开启事务
                        }
                        // 提交事务
                        // 让dao类的save或者update方法正常的执行下去
                        return method.invoke(dao, args);
                    }
                });
        // 返回代理对象
        return proxy;
    }
}

CGLIB的代理技术
public static OrderDaoImpl getProxy(){
    // 创建CGLIB核心的类
    Enhancer enhancer = new Enhancer();
    // 设置父类
    enhancer.setSuperclass(OrderDaoImpl.class);
    // 设置回调函数
    enhancer.setCallback(new MethodInterceptor() {
        @Override
        public Object intercept(Object obj, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            if("save".equals(method.getName())){
                // 记录日志
                System.out.println("记录日志了...");
            }
            return methodProxy.invokeSuper(obj, args);
        }
    });
    // 生成代理对象
    OrderDaoImpl proxy = (OrderDaoImpl) enhancer.create();
    return proxy;
}

两种方式:

xml 和 注解

xml配置

1) 编写切面类

@Component
public class MyAspectXml {
    // 定义通知
    public void log(){
        System.out.println("记录日志...");
    }
}

2) 配置AOP 以下都是AspectJ框架的AOP方式 不是Spring自带的AOP,后者了解即可

切面类 切面类方法 切入点表达式

    
    
        
        
    


在配置切入点的时候,需要定义表达式,格式如下:execution(public * *(..)),具体展开如下:
* 切入点表达式的格式如下:
    * execution([修饰符] 返回值类型 包名.类名.方法名(参数))

* 修饰符可以省略不写,不是必须要出现的。
* 返回值类型是不能省略不写的,根据你的方法来编写返回值。可以使用 * 代替。
* 包名例如:com.itheima.demo3.BookDaoImpl
    * 首先com是不能省略不写的,但是可以使用 * 代替
    * 中间的包名可以使用 * 号代替
    * 如果想省略中间的包名可以使用 .. 

* 类名也可以使用 * 号代替,也有类似的写法:*DaoImpl
* 方法也可以使用 * 号代替
* 参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..

通知类型



1. 前置通知
* 在目标类的方法执行之前执行。
* 配置文件信息:
* 应用:可以对方法的参数来做校验

2. 最终通知
* 在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。
* 在配置文件中编写具体的配置:
* 应用:例如释放资源

3. 后置通知
* 方法正常执行后的通知。       
* 在配置文件中编写具体的配置:
* 应用:可以修改方法的返回值

4. 异常抛出通知
* 在抛出异常后通知
* 在配置文件中编写具体的配置: 
* 应用:包装异常的信息

5. 环绕通知
* 方法的执行前后执行。
* 在配置文件中编写具体的配置:
* 要注意:目标的方法默认不执行,需要使用ProceedingJoinPoint对来让目标对象的方法执行。


注解

* @Aspect               -- 定义切面类的注解
* @Before               -- 前置通知
* @AfterReturing        -- 后置通知
* @Around               -- 环绕通知(手动执行)
* @After                -- 最终通知
* @AfterThrowing        -- 异常抛出通知

配置切入点表达式

@Aspect
public class MyAspectAnno {
    @Before(value="execution(public void com.lzz.demo.CustomerDaoImpl.save())")
    public void log(){
        System.out.println("记录日志...");
    }
}

在配置文件中开启自动代理


Spring自身的AOP方式链接
https://www.yiibai.com/spring/spring-aop-examples-advice.html

JDBC + 事务

JDBC

JdbcTemplate       Spring框架提供的
HibernateTemplate  Spring框架整合Hibernate框架

1) 自己new        
@Test
public void run1(){
    // 创建连接池,先使用Spring框架内置的连接池
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql:///spring");
    dataSource.setUsername("root");
    dataSource.setPassword("root");
    // 创建模板类
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    // 完成数据的添加
    jdbcTemplate.update("insert into t_account values (null,?,?)", "测试",10000);
}

2) 交给IOC

选择一个连接池

* Spring自带的数据库连接池

    
    
    
    


* DBCP连接池

    
    
    
    


* C3P0连接池

    
    
    
    


* Spring管理模板类

        


jdbcTemplate 在DAO层注入
或者继承JdbcDaoSupport类 注入DataSource 用getJdbcTemplate()得到

事务 三种

编程式事务 手动编写代码
声明式事务 基于AspectJ的XML方式和注解方式

PlatformTransactionManager 平台事务管理器 需要注入DataSource
TransactionDefinition 事务定义信息(事务的隔离级别,传播行为,超时,只读)
TransactionStatus  事务的状态

1) 编程式事务

1. 步骤一:配置一个事务管理器,Spring使用PlatformTransactionManager接口来管理事务,所以需要使用到他的实现类
    
    
        
    

2. 步骤二:配置事务管理的模板
    
    
        
    

3. 步骤三:在需要进行事务管理的类中,注入事务管理的模板.
    
        
        
    

4. 步骤四:在业务层使用模板管理事务:
    // 注入事务模板对象
    private TransactionTemplate transactionTemplate;
    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    public void pay(final String out, final String in, final double money) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {

            protected void doInTransactionWithoutResult(TransactionStatus status) {
                // 扣钱
                accountDao.outMoney(out, money);
                int a = 10/0;
                // 加钱
                accountDao.inMoney(in, money);
            }
        });
    }

2) 声明式事务

xml的方式

1. 步骤一:配置事务管理器


    


2. 步骤二:配置事务增强


    
        
        
        
    


3. 步骤三:配置AOP的切面


    


* 注意:如果是自己编写的切面,使用标签,如果是系统制作的,使用标签。

4. 步骤四:编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {

    @Resource(name="accountService")
    private AccountService accountService;

    @Test
    public void run(){
        accountService.pay("lzz", "美美", 1000);
    }
}


注解的方式

1. 步骤一:配置事务管理器


    


2. 步骤二:开启注解事务



3. 步骤三:在业务层上添加一个注解:@Transactional

4. 编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {

    @Resource(name="accountService")
    private AccountService accountService;

    @Test
    public void run(){
        accountService.pay("lzz", "美美", 1000);
    }
}
@Transactional 使用细节
@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
虽然 @Transactional注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。
另外,@Transactional注解应该只被应用到public方法上,这是由Spring AOP 的本质决定的。如果你在protected、private 或者默认可见性的方法上使用@Transactional注解,这将被忽略,也不会抛出任何异常。
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。
关于Spring事务的隔离级别节
Dao层配置事务 需要Service层调用 那么Service相当于A Dao相当于B 

* PROPAGATION_REQUIRED(默认值) -- A中有事务,使用A中的事务.如果没有,B就会开启一个新的事务,将A包含进来.(保证A,B在同一个事务中),默认值!!
* PROPAGATION_SUPPORTS          -- A中有事务,使用A中的事务.如果A中没有事务.那么B也不使用事务.
* PROPAGATION_MANDATORY         -- A中有事务,使用A中的事务.如果A没有事务.抛出异常.

* PROPAGATION_REQUIRES_NEW(记)-- A中有事务,将A中的事务挂起.B创建一个新的事务.(保证A,B没有在一个事务中)
* PROPAGATION_NOT_SUPPORTED     -- A中有事务,将A中的事务挂起.
* PROPAGATION_NEVER             -- A中有事务,抛出异常.

* PROPAGATION_NESTED(记)     -- 嵌套事务.当A执行之后,就会在这个位置设置一个保存点.如果B没有问题.执行通过.如果B出现异常,运行客户根据需求回滚(选择回滚到保存点或者是最初始状态)

你可能感兴趣的:(JavaWeb,SSM框架)