Spring

Spring

1.0 理念

1.1 优点

  • Spring是一个开源免费的框架!
  • Spring'是一个轻量级非入侵框架
  • 控制反转(IOC)面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持

Spring就是一个轻量级控制反转和面向切面编程的框架

1.2 模块

1.3 弊端

  • 发展时间太久了,违背了原来的理念,配置十分的繁琐,俗称配置炼狱

1.4 IOC理论

  • 这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建,系统的耦合性大大降低了,可以更加专注在业务的实现上,将控制权交给用户

  • 在业务中,用户的需求可能会影响我们的代码,我们需要根据客户的需求去修改源代码,如果程序代码非常庞大,修改一次非常的昂贵

  • 我们使用一个Set接口实现,将控制权交给用户 被动的接受对象

  •     private UserDao userDao;
        //利用set进行注入
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        public void getUser() {
            userDao.getUser();
        }
    
  • 系统的的耦合性大大的降低了

1.5 IOC本质

* IOC实质是一种理论,DI(依赖注入)是实现IOC的一种方法
* IOC是Spring的核心内容,使用多种方式来实现IOC,可以使用XML配置,也可以使用注解,新版的spring也可以零配置实现
* Spring 在初始化的时候先读取配置文件,根据配置文件创建组织对象进入容器中,使用时在将对象取出

1.6 Hello Spring

  • 编写 hello class
public class Hello {
    private String name;

    public Hello() {
    }

    public Hello(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

  • 编写spring 配置文件
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--使用spring创建对象  在spring中这些都成为bean  -->
    <bean id="hello" class="com.immortal.pojo.Hello">
        <property name="name" value="immortal" ></property>
    </bean>

</beans>
  • 测试
public static void main(String[] args) {
        //获取spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		//get bean
        Hello hello = context.getBean("hello", Hello.class);

        System.out.println(hello);
    }

1.7 IOC创建对象的方式

  • 使用无参构造器赋值 默认

  • 使用构造器赋值

    • 下标赋值

    • <bean id="exampleBean" class="examples.ExampleBean">
          <constructor-arg index="0" value="7500000"/>
          <constructor-arg index="1" value="42"/>
      </bean>
      
    • 类型

    • <bean id="exampleBean" class="examples.ExampleBean">
          <constructor-arg type="int" value="7500000"/>
          <constructor-arg type="java.lang.String" value="42"/>
      </bean>
      
    • 通过参数名进行赋值

    • <beans>
          <bean id="beanOne" class="x.y.ThingOne">
              <constructor-arg ref="beanTwo"/>
              <constructor-arg ref="beanThree"/>
          </bean>
      
          <bean id="beanTwo" class="x.y.ThingTwo"/>
      
          <bean id="beanThree" class="x.y.ThingThree"/>
      </beans>
      
  • spring在加载配置文件的时候,会把容器中所有的对象进行初始化

1.8 别名 alias

  • alias标签

  • <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--使用spring创建对象  在spring中这些都成为bean  -->
        <bean id="hello" class="com.immortal.pojo.Hello">
            <property name="name" value="immortal" ></property>
        </bean> 
        <!--别名 alias  hello 和 aliasHello 都可以使用   -->	
        <alias name="hello" alias="aliasHello"></alias>
    
    </beans>
    
  • bean name属性 别名

  • <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--使用spring创建对象  在spring中这些都成为bean
            我们一般使用name属性去起别名 ,可是设置多个 用逗号隔开
         -->
        <bean id="hello" class="com.immortal.pojo.Hello" name="aliasHello">
            <property name="name" value="immortal" ></property>
        </bean>
    </beans>
    

1.9 Import

  • 导入其他的spring 配置文件

  • <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    	<!--导入beans配置文件-->
       <import resource="beans.xml"></import>
    
    </beans>
    

2.0 DI 依赖注入

  • 构造器注入 上面有

  • 环境搭建

    • Student

    • public class Student {	
      	private String name;
          private Address address;
          private String[] book;
          private List<String> habbys;
          private Map<String,String> card;
          private Set<String> game;
          private Properties info;
          private String wife;
      }
      
    • Address

    • public class Address {	
      }
      
    • beans.xml spring配置文件

  • Set 方式注入 重点

    • <?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
              https://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <!--使用spring创建对象  在spring中这些都成为bean
              我们一般使用name属性去起别名 ,可是设置多个 用逗号隔开
           -->
          <bean id="address" class="com.immortal.pojo.Address">
      
          </bean>
      
      
          <bean id="student" class="com.immortal.pojo.Student" name="s">
              <!--普通值的注入 value-->
              <property name="name" value="immortal"/>
              <!--引用值的注入 ref-->
              <property name="address" ref="address"/>
              <!--数组的注入-->
              <property name="book">
                  <array>
                      <value>汇编入门到入狱</value>
                      <value>Java入门到放弃</value>
                      <value>C语言程序设计</value>
                  </array>
              </property>
              <!--List注入-->
              <property name="habbys">
                  <list>
                      <value>学BUG</value>
                      <value>写BUG</value>
                      <value>改BUG</value>
                  </list>
              </property>
              <!--Map注入-->
              <property name="card">
                  <map>
                      <entry key="身份证" value="2222222222222222222"></entry>
                  </map>
              </property>
              <!--Set注入-->
              <property name="game">
                  <set>
                      <value>LOL</value>
                      <value>CS</value>
                      <value>DNF</value>
                  </set>
              </property>
              <!--Null注入-->
              <property name="wife">
                  <null/>
              </property>
      
              <!--propertys注入-->
              <property name="info">
                  <props>
                      <prop key="driver">mysql</prop>
                      <prop key="url">mysql</prop>
                      <prop key="user">root</prop>
                      <prop key="pwd">123456</prop>
                  </props>
              </property>
          </bean>
      
      </beans>
      
  • 扩展方式注入

  • P命名空间 需要导入约束 p=property

  • <?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:p="http://www.springframework.org/schema/p"			<!--导入命名空间-->
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.immortal.pojo.User" p:name="immortal" p:age="10"></bean>
    </beans>
    
  • 为了测试方便这里导入junit

  •  <!-- https://mvnrepository.com/artifact/junit/junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
    
  • C命名空间 需要导入约束 c= constructor

  • <?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:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"	
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--导入命名空间-->
        <bean id="user" class="com.immortal.pojo.User" p:name="immortal" p:age="10"></bean>
    
    
        <bean id="u" class="com.immortal.pojo.User" c:age="10" c:name="immortal"></bean>
    </beans>
    

2.1 Bean的作用域

  • 单例模式

  • <bean id="user" class="com.immortal.pojo.User" scope="singleton"></bean>
    
  • 原型模式 多个对象

  • <bean id="user" class="com.immortal.pojo.User"  scope="prototype"></bean>
    
  • 其余的只能在web中使用

2.2 Bean的自动装配

  • 自动装配时Spring满足bean依赖的一种方式

    • spring在上下文z中自动寻找,Bean自动装配,
  • 在spring有三种装配的的方式

    • xml
    • java显示配置
    • 隐式的自动装配 重要
  • <?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:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="cat" class="com.immortal.pojo.Cat"></bean>
        <bean id="dog" class="com.immortal.pojo.Dog"></bean>
    
        <!--
           byName会在上下文中寻找和自己set方法后面对应值的bean id
           byTypy会在上下文中寻找和自己属性一样的bean
           -->
    
        <bean id="person" class="com.immortal.pojo.Person" autowire="byName">
            <property name="name" value="immortal"/>
        </bean>
    
    </beans>
    

2.3 使用注解完成自动装配

  • 要使用注解须知

    • 导入配置

    • 配置注解的支持

    • <?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
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              https://www.springframework.org/schema/context/spring-context.xsd">
              <!--开启注解支持-->
              <context:annotation-config/>
      
      </beans>
      
  • @Autowired

    • 直接在属性在使用,也可以在set方法上使用 可以去掉Set方法
    • 使用Autowired可以不用编写set方法,因为它底层使用反射实现的
  • @Qualifier

    • 指定装配的bean值注入 一般与@Autowired一起使用

    •    @Autowired
         @Qualifier(value = "dog")
         private Dog dog;
      
  • @Resource 和Autowired的区别

    • 都是用于自动装配,都可以放在属性字段上
    • @Autowired 默认byType实现通过 找不到byName的方式实现的
    • @Resource 默认通过byName的方式实现的,找不到则通过byType实现,在找不到就报错

2.4 使用注解开发

  • 使用注解开发需要开启注解支持,扫描指定的包

  • <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
            <!--扫描包-->
            <context:component-scan base-package="com.immortal.pojo"/>
            <!--开启注解支持        -->
            <context:annotation-config/>
    
    </beans>
    
  • @Component  //组件  说明这个被类被spring托管了  用在类上
    @Value // 注入值 用在属性,set方法上
    
  • 衍生的注解 Component,我们在web开发中,会按照mvc三层架构分层!

    • dao @Repository
    • service @Service
    • controller @Controller
    • 将类放入容器中
  • 作用域的注解scope

    • @Scope

    • package com.immortal.pojo;
      
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.context.annotation.Scope;
      import org.springframework.stereotype.Component;
      
      @Component
      @Scope(value = "singleton")
      public class User {
      
          @Value("immortal")
          private String name;
      
          @Override
          public String toString() {
              return "User{" +
                      "name='" + name + '\'' +
                      '}';
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      

2.5 使用java的方式配置Spring

  • @Configuration 说明是spring的配置类

  • @ComponentScan 指定扫描的包

  • @Import 导入其他配置类

  • @Bean 指定是一个bean

  • @Configuration
    @ComponentScan("com.immortal")
    @Import(LogConfig.class)
    public class ImmortalConfig {
    	
        //注册一个bean,相当于一个bean标签
        //这个方法的名字,就是标签的id属性
        //这个方法的返回值,就相当于class属性
        
        @Bean 
        public User user(){
            return new User();   //这里返回的就是要注入的对象
        }
    }
    
  • 测试的话要用这个类 注解的

  •  	@Test
        public void Test(){
            ApplicationContext context  = new AnnotationConfigApplicationContext(ImmortalConfig.class);
      
            User user = (User) context.getBean("user");
      
            System.out.println(user.toString());
        }
    

2.6 代理模式

  • 代理模式的好处

    • 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
    • 公共业务交给代理角色,实现了业务的分工
    • 公共业务发生扩展,方便集中管理
  • 缺点

    • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率降低
  • 静态代理

    • 接口

    • //租房接口
      public interface Rent {
          public void rent();
      }
      
    • 真实角色

    • //房东
      public class House implements Rent{
      
          public void rent() {
              System.out.println("房东出租房子...");
          }
      }
      
      
    • 代理角色

    • //中介
      public class Client implements Rent{
      
          private House house;
      
      
          public Client(House house) {
              this.house = house;
          }
      
          public void rent() {
              seeHouse();
              house.rent();
              contract();
          }
      
          public void seeHouse(){
              System.out.println("中介带看房啊...");
          }
      
          public void contract(){
              System.out.println("中介签合同...");
          }
      
      }
      
      
    • 客户

    • //客户
      public class Proxy {
      
          public static void main(String[] args) {
              Client client = new Client(new House());
      
              client.rent();
          }
      }
      
      
  • 纵向开发 横切进去

  • 动态代理

    • 动态代理和静态代理角色一样

    • 动态代理使动态生成的,不是我们直接写的

    • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理

      • 基于接口----jdk 动态代理
      • 基于类: cglib
      • java字节码 java ssist
    • 需要了解2个类

    • proxy 代理 invocationHandler 调用处理程序

    • 解决了静态代理的问题

    • public class HouseInvocationHandler implements InvocationHandler {
      
          private Object target;
      
      
          public void setTarget(Object target) {
              this.target = target;
          }
          public Object getProxy(){
             return Proxy.newProxyInstance(this.getClass().getClassLoader(), 							target.getClass().getInterfaces(), this);
          }
      
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              method.invoke(target, args);
              System.out.println(method.getName());
              return null;
          }
      }
      

2.7 AOP 什么是AOP?

(Aspect Oriented programming) 面向切面编程,通过预编译的方式和运行期间动态代理实现程序功能的统一维护的一种技术

,AOP是OOP的延续,是软件开发的的一个热点,在Spring中是一个重要内容

2.8 AOP在spring中的作用

提供声明式事务,允许用户自定义切面

要使用AOP功能,需要先导包

 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
  • Spring 实现AOP 日志功能

  • 方式一

    • 使用spring的API 接口 实现spring接口 MethodBeforeAdvice

    • package com.immortal.log;
      
      import org.springframework.aop.MethodBeforeAdvice;
      
      import java.lang.reflect.Method;
      
      public class Log implements MethodBeforeAdvice {
      
          public void before(Method method, Object[] objects, Object o) throws Throwable {
              System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
          }
      }
      
    • 实现类

    • package com.immortal.service;
      
      public class UserServiceImpl implements UserService {
          public void add() {
              System.out.println("add a user");
          }
      
          public void updata() {
              System.out.println("updata a user");
          }
      
          public void delete() {
              System.out.println("delete a user");
          }
      
          public void query() {
              System.out.println("query a user");
          }
      }
      
    • spring 配置文件

    • <?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"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              https://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              https://www.springframework.org/schema/aop/spring-aop.xsd">
      
          <bean id="userService" class="com.immortal.service.UserServiceImpl"></bean>
      
          <bean id="log" class="com.immortal.log.Log"></bean>
      
          <!--配置AOP-->
          <aop:config>
             	<!--execution表达式   切入点的筛选规则--->
              <aop:pointcut id="pointcut" expression="execution(* com.immortal.service.UserServiceImpl.*(..))"/>
              	<!--将功能放在切入点上--->
              <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
          </aop:config>
      </beans>
      

      1、execution(): 表达式主体。

      2、第一个*****号:表示返回类型,*号表示所有的类型。

      3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,子孙包下所有类的方法。

      4、第二个**号:表示类名,*号表示所有的类。

      5、**(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

  • 方式二 自定义类

    • 自定义一个类

    • public class diypointcut {
      
          public void before(){
              System.out.println("before();");
          }
      
          public void after(){
              System.out.println("after();");
          }
      }
      
    • 在spring配置文件中配置

    • <?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"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              https://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              https://www.springframework.org/schema/aop/spring-aop.xsd">
          
          <bean id="diy" class="com.immortal.diy.diypointcut"/>
          <!--配置AOP-->
          <aop:config>
              <!--定义切面 -->
              <aop:aspect ref="diy">
                  <!--定义切入点 -->
                  <aop:pointcut id="pointcut" expression="execution(* com.immortal.service.UserServiceImpl.*(..))"/>
      			 <!--定义点之前执行的方法 -->
                  <aop:before method="before" pointcut-ref="pointcut"/>
                  <aop:after method="after" pointcut-ref="pointcut"/>
      
              </aop:aspect>
          </aop:config>
      </beans>
      
  • 方式三 注解实现

    • @Aspect切入点

    • @Component
      @Aspect
      public class AnnoPointCut {
      
          @Before("execution(* com.immortal.service.UserServiceImpl.*(..))")
          public void before(){
              System.out.println(" before();");
          }
      }
      
    • @Service 组件

      @Service
      public class UserServiceImpl implements UserService {
          public void add() {
              System.out.println("add a user");
          }
      
          public void updata() {
              System.out.println("updata a user");
          }
      
          public void delete() {
              System.out.println("delete a user");
          }
      
          public void query() {
              System.out.println("query a user");
          }
      }
      
    • 配置文件spring

    • <?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"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              https://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              https://www.springframework.org/schema/aop/spring-aop.xsd">
      
          <context:component-scan base-package="com.immortal"/>
          <context:annotation-config/>
          <!--开启aop注解支持-->
          <aop:aspectj-autoproxy/>
      </beans>
      
posted @ 2020-12-12 22:21  immortal_mode  阅读(107)  评论(0)    收藏  举报