Spring

一、引言

Spring概念:    是轻量级的javaEE解决方案,众多优秀设计模式的组合 
			   代码侵入性小——轻量级的JavaEE解决方案
设计模式概念:  特定的代码解决特定的问题

二、工厂模式

  • 好处: 解耦和
  • 原理 : 读配置文件,获得类的全限命名,通过反射创建对象.
  • Spring 默认创建的对象为单列。开发中创建一次对象的情况居多。

2.1 Set注入

  • 原理: 底层通过调用该类中的set方法 进行属性赋值
  • 注意: 使用set注入时,需要给该类提供对应的set方法

2.1.1 基本数据类型和Sring 的注入

    <bean id="user" class="com.baizhi.entity.User" scope="prototype">  
    //默认为单例(简单对象) singleton scope 属性
        <property name="id">
            <value>1</value>
        </property>
        <property name="name">
            <value>张三</value>
        </property>
        <property name="password">
            <value>123456</value>
        </property>

        <!--数组-->
        <property name="aarey">
            <array>
                <value>张三</value>
                <value>李四</value>
                <value>老王</value>
            </array>
        </property>

        <!--list集合-->
        <property name="list">
            <list>
                <value>oooo</value>
                <value>ppppppp</value>
            </list>
        </property>

        <property name="set">
            <set>
                <value>aaaaaaaaaa</value>
                <value>bbbbbbbb</value>
            </set>
        </property>

        <!--MAp集合-->
        <property name="hashMap">
            <map>
                <entry key="1">
                    <value>sssadad</value>
                </entry>

                <entry key="2">
                    <value>adaddafffa</value>
                </entry>
            </map>
        </property>

        <!--properces-->
        <property name="properties">
            <props>
                <prop key="a">aaaaaaa</prop>
                <prop key="b">bbbbbbbbbbbbbb</prop>
            </props>
        </property>
    </bean>
    
public class User {
    private int id;
    private String name;
    private String password;

    private String[]  aarey;
    private List<String> list;
    private Set<String> set;
    private Map<Integer,String> hashMap;
    private Properties properties;

    public User() {
    }

    public User(int id, String name, String password, String[] aarey, List<String> list, Set<String> set, Map<Integer, String> hashMap, Properties properties) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.aarey = aarey;
        this.list = list;
        this.set = set;
        this.hashMap = hashMap;
        this.properties = properties;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String[] getAarey() {
        return aarey;
    }

    public void setAarey(String[] aarey) {
        this.aarey = aarey;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public Set<String> getSet() {
        return set;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public Map<Integer, String> getHashMap() {
        return hashMap;
    }

    public void setHashMap(Map<Integer, String> hashMap) {
        this.hashMap = hashMap;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", aarey=" + Arrays.toString(aarey) +
                ", list=" + list +
                ", set=" + set +
                ", hashMap=" + hashMap +
                ", properties=" + properties +
                '}';
    }
public class test_all {
    private ClassPathXmlApplicationContext AC = new ClassPathXmlApplicationContext("/applicationContext.xml");
    @Test
    public void test2(){
        User user =(User) AC.getBean("user");
        System.out.println("----------"+user);//默认为单例(简单对象)
    }
}
//-User{id=1, name='张三', password='123456', aarey=[张三, 李四, 老王], list=[oooo, ppppppp], set=[aaaaaaaaaa, bbbbbbbb], hashMap={1=sssadad, 2=adaddafffa}, properties={b=bbbbbbbbbbbbbb, a=aaaaaaa}}

2.1.2 Spring 自定义类型进行注入

在这里插入图片描述


2.2 构造注入

  • 原理: 底层通过调用有参构造 为对应的属性进行赋值操作
  • 注意:提供有参构造
 <bean id="acount"  class="com.baizhi.entity.Acount">
        <constructor-arg>
            <value>6</value>
        </constructor-arg>

        <constructor-arg>
            <value>zhangsan</value>
        </constructor-arg>
        <constructor-arg>
            <value>123</value>
        </constructor-arg>
        <constructor-arg>
            <value>123</value>
        </constructor-arg>
    </bean>
	//获取工厂
   private ClassPathXmlApplicationContext AC = new ClassPathXmlApplicationContext("/applicationContext.xml");

   @Test
    public void test5(){
        //构造注入
        Acount acount =(Acount) AC.getBean("acount");
        System.out.println("-------"+acount);
    }
    //Acount{id=6, name='zhangsan', password='123', balance=123.0}

2.3 自动注入

  • 应用:只应用于自定义类型的注入 autowire=“byType” 根据属性类型进行注入
public class Student {
    private int code;
    private String name;
    private int age;
    ....set get toString +构造;
    }
//    注入book
    private Book books;
<!--自定义对象注入的三种方式   autowire 自动扫描注入已有的类型 可bytype-->
     <bean id="student" class="com.baizhi.entity.Student" autowire="byName">
         <property name="code">
             <value>22</value>
         </property>
         <property name="name">
             <value>qwqw</value>
         </property>
         <property name="age">
             <value>23</value>
         </property>
<!--
         <property name="books" ref="books">
         </property>-->
     </bean>

   		Student student = (Student)AC.getBean("student");
        System.out.println("-------"+student);
        System.out.println("-------"+student.getBooks());
        
Student{code=22, name='qwqw', age=23, books=Book{id=1, name='qqqq', price='2232'}}
Book{id=1, name='qqqq', price='2232'}

2.4 IOC 反转控制(Inversion Of Control)

  • 控制:给对象中属性进行赋值
  • 反转:把给对象属性赋值的权利 由代码反转到配置文件中

2.5 DI 依赖注入 (Dependency Injection)

  • 当一个类型需要另一个类型时,就意味这两个类型存在依赖关系。我们就可以把一个类型作为另一个类型的属性进行注入
    在这里插入图片描述

三、 FactoryBean技术

  • 作用: 创建复杂对象
  • 复杂对象: 不能通过new的方式创建的对象
  • 获取的对象不是该类的对象,而是该类创建的复杂对象。
  • Connection connection1 = (Connection)AC.getBean("&connection"); 此写法可以获取到该类的对象。
    在这里插入图片描述

3.1 数据库连接对象的创建

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd

                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!--名字空间-->
    <context:property-placeholder location="classpath:/jdbc.properties"/>

    <!--复杂対象的创建 连接对象-->
    <bean id="connection" class="com.baizhi.factoryBean.MyConnection">
        <property name="driver">
            <value>${driverClassName}</value>
        </property>
        <property name="url">
            <value>${url}</value>
        </property>
        <property name="username">
            <value>${name}</value>
        </property>
        <property name="password">
            <value>${password}</value>
        </property>
    </bean>
  </beans>
	driverClassName=oracle.jdbc.OracleDriver
	url=jdbc:oracle:thin:@localhost:1521:xe
	name=XX
	password=XX
public class MyConnection implements FactoryBean<Connection> {
    private String driver;
    private String url;
    private String username;
    private String password;

    //<editor-fold desc="set/get">
    public String getDriver() {
        return driver;
    }
    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    //</editor-fold>

    //书写 创建复杂对象的步骤
    @Override
    public Connection getObject() throws Exception {
        //创建Connection对象的步骤
        Class.forName(driver);
        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }

    // 返回创建的复杂对象的类型
    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

    //控制复杂对象的创建次数,根据创建复杂对象的特点
    // 设置返回值  连接对象返回false   每一创建一个  比较安全
    @Override
    public boolean isSingleton() {
        /*
         * false:  不单例  每次都会创建新的对象
         * true:   单例   应用只会创建一个对象
         * */
        return false;
    }

3.2 SqlSessionFactory 的创建

  • src\main\resources\mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>
	
<!-- 读取配置文件 -->
	<properties resource="jdbc.properties" />

	<!--数据库连接相关的参数 -->
	<environments default="oracle">
		<environment id="oracle">
			<transactionManager type="JDBC"></transactionManager>
			<dataSource type="POOLED">
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}" />
				<property name="username" value="${username}" />
				<property name="password" value="${password}" />
			</dataSource>
		</environment>
	</environments>

	<!-- mapper 文件的注册 -->
	<mappers>

	</mappers>
</configuration>
public class MySqlSessionFactory  implements FactoryBean<SqlSessionFactory> {

    //书写创建SqlSessionFactory的步骤
    @Override
    public SqlSessionFactory getObject() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        return  sqlSessionFactory;
    }

    //返回复杂对象的类型
    @Override
    public Class<?> getObjectType() {
        return  SqlSessionFactory.class;
    }

   // 创建复杂的对象的次数
    @Override
    public boolean isSingleton() {
        return  true;
    }
}
		//test
        SqlSessionFactory sqlSessionFactory =(SqlSessionFactory) AC.getBean("sqlSessionFactory");
        System.out.println("---------"+sqlSessionFactory);
//        SqlSession sqlSession = sqlSessionFactory.openSession();
//        sqlSession.rollback();
//        sqlSession.commit();
//        sqlSession.close();

3.3 Spring创建对象的生命周期

  • 什么时候被创建?
  • 什么时候被销毁?
  Spring工厂被创建则对象被创建   这种创建对象的方式属于饿汉创建   效率高  
  Spring工厂被销毁  则对象被销毁 
      private ClassPathXmlApplicationContext AC = new ClassPathXmlApplicationContext("/applicationContext.xml");
      AC.close();

3.4 配置信息参数化

  • 把spring配置文件中经常需要修改的内容抽取到小配置文件中
  • 1.准备小配置文件 jdbc.properties
driverClassName=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
name=hr
password=hr
  • 2.把小配置文件读取到spring的配置文件中
    在这里插入图片描述

四、Aop(Aspect Oriented Programming ) 面向切面编程

  • 名词
原始类: 负责核心功能的类
原始方法: 原始类中的方法

代理类: 给原始类的原始方法添加额外功能的类

静态代理本质:  把额外功能拆分到代理类中,原始类只负责核心功能,有利于代码的维护

 缺点:   1. 类过载
	     2. 额外功能代码冗余

4.1 .静态代理设计模式(static Proxy)

在这里插入图片描述

4.1.1 书写原始类

public interface UserService {
     //注册
    public  int  register(String username);
}
//原始类
public class UserServiceImpl  implements  UserService {
    @Override
    public int  register(String username) {
        System.out.println("我是带有一个参数的注册方法");
        return  666;
    }
}

4.1.2 在Spring的配置文件中,配置的Bean相关信息

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置原始类的相关信息-->
    <bean id="userService" class="com.baizhi.fiels.dynamicProxy.UserServiceImpl">
    </bean>

    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pc" expression="execution(*  register(String))"></aop:pointcut>

        <!--配置类切点-->
        <!--<aop:pointcut id="pc" expression="execution(*  *..UserServiceImpl.register(String,..))"></aop:pointcut>-->

        <!--组装切面 :把那一个 额外功能加给那一个 方法-->
        <!-- <aop:pointcut id="pc" expression="execution(* com.baizhi.dynimicproxy..UserServiceImpl.register(String,..))"></aop:pointcut>-->
        <aop:advisor advice-ref="around" pointcut-ref="pc"></aop:advisor>
    </aop:config>
</beans>

4.1.3 书写额外功能

public class Around implements MethodInterceptor {
    /*
    * 方法的作用:  额外功能运行在原始方法之前后执行
    * 参数的作用:mi  代表添加的原始方法对应的对象的封装
    *           Object 代表  原始方法执行过后的返回值
    * */
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        System.out.println("我是在原始方法之前执行的额外功能");

        //执行原始方法
        Object ret = mi.proceed();

        System.out.println("我是在原始方法之后执行的额外功能");
        System.out.println(ret);
        return  ret;
    }
}

4.2 动态代理设计模式 (Dynamic Proxy)

4.2.1 JDK方式创建代理对象(基于接口) (默认)

public interface UserService {
     //注册
    public  int  register(String username);
}
public class UserServiceImpl  implements  UserService {
    @Override
    public int  register(String username) {
        System.out.println("有一个参数的注册方法");
        return  666;
    }

}

public class testMy_JDKProxy {
    @Test
    public void test1() {
        final UserService us = new UserServiceImpl();

        //现实InvocationHandler 接口
        InvocationHandler hi = new InvocationHandler() {
            /*
             *  method:原始方法
             *  args:原始的方法参数
             *  返回值:原始方法的返回值
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("---------before -------");
                //原始方法运行
                //userService.login("suns", "123456")
                //userService.register(user);
                Object ret = method.invoke(us, args);
                System.out.println("---------after -------");

                return ret;
            }
        };

        UserService usp = (UserService) Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(), us.getClass().getInterfaces(), hi);
        usp.register("lasa");
    }
}

//---------before -------
//带有一个参数的注册方法
//---------after -------

4.2.2 Cglib方式创建代理对象 (基于父子类继承关系)

public class test_CglibProxy {
    @Test
    public  void test_cgLib(){
        //创建原始类的对象
        final UserService us = new UserServiceImpl();


        //准备额外功能
        InvocationHandler invocationHandler = new InvocationHandler() {
            /*
             * 方法的作用:给原始类添加额外功能
             * 参数的作用:  o 代表代理对象    method代表 原始方法对象   objects代表 原始方法传入的实际参数
             * 返回值:代表 原始方法执行过后的返回值
             * */
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                System.out.println("我是执行在原始方法之前执行的额外功能");

                //调用原始方法 原始对象  原始方法传入的实际参数
                Object ret = method.invoke(us, objects);

                System.out.println("我是执行在原始方法之后执行的额外功能");
                return  ret;
            }
        };

        Enhancer enhancer = new Enhancer();
        //类加载器
        //设置类加载器
        enhancer.setClassLoader(test_CglibProxy.class.getClassLoader());
        //设置父类  原因  通过继承关系  保证代理类与原始类都有相同的方法
        enhancer.setSuperclass(us.getClass());
        //给原始类添加额外功能
        enhancer.setCallback(invocationHandler);

        //构建代理对象
        UserServiceImpl o=(UserServiceImpl) enhancer.create();
        o.register("ss");
        
    }
//我是执行在原始方法之前执行的额外功能
//带有一个参数的注册方法
//我是执行在原始方法之后执行的额外功能

五、Spring+MyBatis整合

	建表
	写实体
	定义DAO接口
	Mapper文件实现DAO接口
	Mapper文件注册
	测试

六、Spring中的事务控制

6.1 事物概念

	保证一组DAO操作的完整性 (一起成功  一起失败)
	主要应用在Service层.
	如何控制事务?
	JDBC中:
		 connection.setAutoCommited(false)                                                                               
		 connection.commit();
		 connection.rollback();
   Mybatis:
   	     sqlSession.commit();
         sqlSession.rollback();   

6.2 Spring中控制事务的开发

  • 在Spring中,把事务划分为额外功能,需要通过Spring的动态代理给对应的方法添加事务
  • 步骤
	1.书写原始类
	2.在Spring的配置文件中配置原始类的相关信息
	3.书写额外功能类
	4.配置额外功能类的信息
	5.配置切入点
    6.组装切面
    <!--引入事务额外功能-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--控制事务需要创建连接   创建连接需要连接数据库的相关参数-->
        <property name="dataSource" ref="dataSource">
        </property>
    </bean>

    <!--对于事务的相关描述-->
    <tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
        <tx:attributes>
            <!--给添加到哪一个方法上的事务进行相关表述 支持通配符-->
            <tx:method name="modify*"/>
        </tx:attributes>
    </tx:advice>
    <!--配置切入点-->
    <aop:config>
        <aop:pointcut id="p1" expression="execution(* *..AcountServiceImpl.*(..))"></aop:pointcut>

      <!--组装切面,将额外功能,添加到哪些方法添加额外功能-->
        <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="p1"></aop:advisor>
    </aop:config>

在这里插入图片描述

七 Spring中的事务描述

7.1 隔离属性 isolation

 脏读:   一个事务读取了另一个事务尚未提交的数据
  	isolation="READ_COMMITTED"  解决脏读问题(默认值) (列锁)
  	
 不可重复读: 一个事务中多次查询得到的结果不一致
	isolation="REPEATABLE_READ"   解决不可重复读  (行锁)
	
 幻影读: 一个事务多次统计的结果不一致
	isolation="SERIALIZABLE"   解决幻影读问题   (表锁)

7.2 传播属性 propagation

作用:解决事务嵌套问题(一个事务嵌套了另外一个事务)
	(增删改)默认
   propagation="REQUIRED" 外部有事务则融合到外部事务中,外部没有事务 则开启新的事务                              

  (查询)
   propagation="SUPPORTS"  外部有事务则融合到外部事务中,外部没有事务也不开启新的事务                               

在这里插入图片描述
在这里插入图片描述

7.3 只读属性 readOnly

 默认 read-Only=false      增删改
      read-Only=true       查询   提高查询效率

7.4 超时属性 timeout

 默认值: -1        
  作用:指定等待时长(一个事务占用对应的数据,需要进行等待,才能操作)  
       -1 代表根据数据库的特性,指定对应的等待时长

在这里插入图片描述

7.5 异常属性

默认:
	对于RuntimeException以及子类做回滚操作
    对于Exception进行提交操作
     rollback-for=""   指定那些异常遇到了做回滚操作 
     no-rollback-for="" 指定那些异常做遇到了提交操作

7.6 属性的配置

总结:
	 增删改          
		 isolation="DEFAULT"       
		 propagation="REQUIRED"   
	     read-Only=false     
	     timeout=-1   全用默认值

  查询             
  	 isolation="DEFAULT"       
  	  propagation="SUPPORTS"  
  	  read-Only=true          
  	  timeout=-1   
  • 注意
    在这里插入图片描述
    在这里插入图片描述
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值