Spring初识

导入的maven依赖



 

    org.springframework
    spring-webmvc
    5.2.8.RELEASE

Spring优点

*Spring是一个开源的免费框架(容器)!

*Spring是一个轻量级的,非入侵式的框架!

*控制反装(IOC),面向切面编程(AOP)!

*支持事务的处理,对框架的整合的支持!

总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!
其次是:IOC(控制反转):实际上对象是由Spring创建,管理,装配!

===============================================================

使用Spring来创建对象时,在Spring这些都称为Bean
 类型  变量名称  =  new 类型();
 Hello hello = new Hello();
 id = 变量名
 class = new 的对象
 property 相当于给对象中的属性设置的一个值
<!--  第一种:通过有参下标赋值!  -->
<!--   <bean id="User" class="com.wang.pojo.User">-->
<!--       <constructor-arg index="0" value="王家俊学Spring!"/>-->
<!--  默认通过无参构造创建  -->
<!--       <property name="name" value="王家俊"/>-->
<!--  第二种:通过数据类型创建(如果参数有两个就不好设置了,所以不建议使用!)-->
<!--    <bean id="User" class="com.wang.pojo.User">-->
<!--        <constructor-arg type="java.lang.String" value="王家俊啦啦啦"/>-->
<!--   </bean>-->
<!--ref:引用Spring容器中创建好的对象
    value: 具体的值,具体数据类型
    -->
<!--  第三种:直接通过参数名字赋值!  -->
  <bean id="User" class="com.wang.pojo.User">
      <constructor-arg name="name" value="王家俊要回家!!"/>
  </bean>
<!-- 当在创建bean的时候Spring就已经把他实例化了   -->
<!-- name也可以用作别名 可以空格分隔,逗号分隔,分号分隔  -->
    <bean id="UserT" class="com.wang.pojo.UserT" name="User2 wangjiajun,u3;u4">
        <property name="name" value="王家俊啦啦啦"/>
    </bean>
<!-- 别名  -->
    <alias name="User" alias="wangjiajun"/>
</beans>
property的几种注入方式:

 <bean id="address" class="com.wang.pojo.Address">
        <property name="addr" value="武汉"/>
    </bean>
    <bean id="name" class="com.wang.pojo.Student">
        <!--    第一种普通注入    -->
         <property name="name" value="王家俊"/>
        <!--    第二种bean注入    -->
        <property name="address" ref="address"/>
<!--     第三种:数组注入   -->
        <property name="books">
            <array>
                <value>王家俊学Java</value>
                <value>王家俊学Spring</value>
                <value>王家俊学Spring-Boot</value>
            </array>
        </property>
<!--    list    -->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>看电影</value>
                <value>啪啪啪</value>
            </list>
        </property>
        <property name="card">
            <map>
                <entry key="爱好" value="睡觉"/>
                <entry key="喜欢" value="女人"/>
                <entry key="音乐" value="啦啦"/>
                <entry key="游戏" value="无"/>
            </map>
        </property>
        <property name="games">
            <set>
                <value>LOL</value>
                <value>COC</value>
                <value>BOB</value>
            </set>
        </property>
<!--    NULL值注入    -->
        <property name="wife">
            <null/>
        </property>
        <!--Properties
        key:键值;
        value:尖括号中间
        -->
        <property name="info">
            <props>
                <prop key="driver">20210630</prop>
                <prop key="url">男</prop>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
     </bean>

</beans>

===============================================================

自动装配(Autowire):

<bean id="cat" class="com.wang.pojo.cat"/>
<bean id="dog" class="com.wang.pojo.dog"/>

创建一个猫和一个狗的实体类:

  <bean id="person" class="com.wang.pojo.people" >
        <property name="name" value="王家俊"/>
      <property name="cat" ref="cat"/>
       <property name="dog" ref="dog"/>
    </bean>

用普通的bean注入比较繁琐所以增加了自动注入的方式:

    <bean id="person" class="com.wang.pojo.people" autowire="byName">
        <property name="name" value="王家俊"/>
<!--        <property name="cat" ref="cat"/>-->
<!--        <property name="dog" ref="dog"/>-->
    </bean>

注意:

 byName:会自动在容器上下文中查找,和自己对象set方法后面对应的bean id!

 byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean!

缺点:ByType使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常

使用ByName会去spring容器中寻找是否有此字符串名称id的对象。
3. 如果有,就取出注入;如果没有,就报空指针异常。

Autowired(自动注入)

autowired里面有一个required默认为true,当

@Autowired(required = false)
private cat cat;

这么写的时候,该对象可以为null,否则不允许为空;也等价与Nullable

public people people(@Nullable String people){
    return null;
}

另外:@Autowired是先通过bytype方式寻找,如果Type不唯一在通过ByName的方式寻找和resouces差不多

使用注解开发!

@Component组件,放在类上,说明被Spring管理,就是bean!另外,@Component组件有几个衍生注解

*dao【@Repository】

*service【@Service】

*controller【@Controller】他们四个是注解功能都是等价的

动态代理!!

我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想
【聊聊AOP:纵向开发,横向开发】

、动态代理
动态代理的角色和静态代理的一样 .
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理----JDK动态代理
基于类的动态代理--cglib

【InvocationHandler:调用处理程序】(这个方式是代理类的调用处理程序!先调用这个程序,再由这个程序执行代理类的方法(invoke)!)

Object invoke(Object proxy, 方法 method, Object[] args);
//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接
口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始
类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean

【Proxy : 代理】

//生成代理类
public Object getProxy(){
  return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                 rent.getClass().getInterfaces(),this);
}

代码实现
抽象角色和真实角色和之前的一样!
Rent . java 即抽象角色

//抽象角色:租房
public interface Rent {
  public void rent();
}
Host . java 即真实角色

//真实角色: 房东,房东要出租房子
public class Host implements Rent{
  public void rent() {
    System.out.println("房屋出租");
 }
}
ProxyInvocationHandler. java 即代理角色

public class ProxyInvocationHandler implements InvocationHandler {
  private Rent rent;
  public void setRent(Rent rent) {
    this.rent = rent;}


//生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一
类角色

  public Object getProxy(){
    return Proxy.newProxyInstance(this.getClass().getClassLoader(),
        rent.getClass().getInterfaces(),this);
 }
  // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
  // 处理代理实例上的方法调用并返回结果

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
    seeHouse();
    //核心:本质利用反射实现!
    Object result = method.invoke(rent, args);
    fare();
    return result;
 }
  //看房
  public void seeHouse(){
    System.out.println("带房客看房");
 }
  //收中介费
  public void fare(){
    System.out.println("收中介费");
 }
}

Client . java

//租客
public class Client {
  public static void main(String[] args) {
    //真实角色
    Host host = new Host();
    //代理实例的调用处理程序
    ProxyInvocationHandler pih = new ProxyInvocationHandler();
    pih.setRent(host); //将真实角色放置进去!
    Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类!
    proxy.rent();
 }
}
//抽象角色:租房
public interface Rent {
  public void rent();
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、
深化理解
我们来使用动态代理实现代理我们后面写的UserService!
我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!

public class ProxyInvocationHandler 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);
 }
  // proxy : 代理类
  // method : 代理类的调用处理程序的方法对象.
  public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
    log(method.getName());
    Object result = method.invoke(target, args);
    return result;
 }
  public void log(String methodName){
    System.out.println("执行了"+methodName+"方法");
 }
}

测试!

public class Test {
  public static void main(String[] args) {
    //真实对象
    UserServiceImpl userService = new UserServiceImpl();
    //代理对象的调用处理程序
    ProxyInvocationHandler pih = new ProxyInvocationHandler();
    pih.setTarget(userService); //设置要代理的对象
    UserService proxy = (UserService)pih.getProxy(); //动态生成代理类!
    proxy.delete();
 }
}

动态代理的好处
静态代理有的它都有,静态代理没有的,它也有!
可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
公共的业务由代理来完成 . 实现了业务的分工 ,
公共业务发生扩展时变得更加集中和方便 .
一个动态代理 , 一般代理某一类业务
一个动态代理可以代理多个类,代理的是接口!

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现
程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的
一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使
得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值