zoukankan      html  css  js  c++  java
  • Spring Framework Part3 IoC and Dynamic Proxy

    spring serious of blog edit by 马士兵教育

    Maven方式创建Spring工程

    工程创建

    1.新建项目 选择Maven Project

     

    2.勾选 Create a simple project

     

    3.添加项目信息

     

    l Group id :包名

    l Artifact id:标识名

    l Name:项目名

    依赖引入

    Maven 中央仓库

    地址https://mvnrepository.com/

    使用国内镜像

    创建一个maven的配置文件

    参照:

    http://maven.apache.org/settings.html

    Pom.xml

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
    
    <dependency>
    
    <groupId>org.springframework</groupId>
    
    <artifactId>spring-beans</artifactId>
    
    <version>5.1.7.RELEASE</version>
    
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    
    <dependency>
    
    <groupId>org.springframework</groupId>
    
    <artifactId>spring-context</artifactId>
    
    <version>5.1.7.RELEASE</version>
    
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    
    <dependency>
    
    <groupId>org.springframework</groupId>
    
    <artifactId>spring-core</artifactId>
    
    <version>5.1.7.RELEASE</version>
    
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
    
    <dependency>
    
    <groupId>org.apache.commons</groupId>
    
    <artifactId>commons-lang3</artifactId>
    
    <version>3.9</version>
    
    </dependency>
    
     

    空值注入

    Value标签

    标识空值 或空字符串 “”

    <property name="name"><value></value></property>

    Null标签

    标识Null

    <property name="name"><null></null></property>

    工厂方式注入

    为满足更复杂的需求,Spring也提供了工厂方式来创建更加灵活的Bean。

    留意观察工厂类和实现类的创建次数

    动态工厂

    抽象接口 Car

    public interface Car {
    
    public String getName();
    
    public String getPrice();
    
    }

    实现类 BMW

    public class Bmw implements Car{
    
     
    
    public String getName() {
    
    // TODO Auto-generated method stub
    
    return "别摸我";
    
    }
    
     
    
    public String getPrice() {
    
    // TODO Auto-generated method stub
    
    return "500000RMB";
    
    }
    
    }

    汽车工厂类 CarFactory

    public class CarFactory {
    
     
    
    public Car getCar(String name) throws Exception{
    
     
    
    if (name.endsWith("bmw")) {
    
    return new Bmw();
    
    }else {
    
    throw new Exception("car not fond");
    
    }
    
    }
    
    }

    Bean配置

    <bean id="carFactory" class="com.msb.CarFactory"></bean>
    
    <bean id="car" factory-bean="carFactory" factory-method="getCar" >
    
    <constructor-arg value="bmw"></constructor-arg>
    
    </bean>

    静态工厂

    Bean配置

    <bean id="carStatic" class="com.msb.CarFactoryStatic" factory-method="getCar">
    
     <constructor-arg value="bmw"></constructor-arg>
    
    </bean>

    工厂类

    public class CarFactoryStatic {
    
     
    
    public static Car getCar(String name) throws Exception{
    
     
    
    if (name.endsWith("bmw")) {
    
    return new Bmw();
    
    }else {
    
    throw new Exception("car not fond");
    
    }
    
    }
    
    }
    
     

    autowire自动注入

    使用自动需要在配置文件中bean上添加autowire

    <bean id="person" class="com.msb.Person" autowire="byName">
    
    </bean>
    
    <bean id="pet" class="com.msb.Pet">
    
      <property name="name" value="kele"></property>
    
    </bean>
    
     

    实体

    public class Person {
    
     
    
    private String name;
    
    private Pet pet;
    
    }
    
    public class Pet {
    
     
    
    private String name;
    
    }

    可选两种类型

    byName

    byName方式自动注入:要求注入的beanid必须和被注入的bean对象的属性名一致

    byType

    byType方式自动注入:要求注入的bean对象类型与被注入的bean对象类型一致,并且在配置文件中的Bean相同类型必须唯一

    如果存在多个,会抛异常:

    No qualifying bean of type 'com.msb.Pet' available: expected single matching bean but found 2: pet,pet2

    全局空值自动注入

    在首行Beans标签下添加default-autowire属性。

    <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           http://www.springframework.org/schema/beans/spring-beans.xsd"
    
     
    
    default-autowire="byType"
    
    >

    annotation注解注入

    使用注解需要导入AOP包

    在配置文件中添加Context约束

    <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: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.xsd
    
    "
    
    >

     

    <context:component-scan>

    <context:component-scan base-package="com.msb"></context:component-scan>

    component-scan可以自动扫描包内容,并注册BeanSpring容器

    @Component

    在需要注册到容器的类上添加@Component标签,标识这个类由Spring容器接管

    约定大于配置

    在一个类上添加@Component默认会使用首字母小写的类名作为ID注册到Spring容器。

    如果需要手动指定Bean Id可以使用@Component("p")

    同属@Component的额外三个注解

    @Controller @Service @Repository

    这三个注意在MVC开发中会经常用到,除了注解名字和Component不一样之外,其余功能都一样。

    Spring额外提供这三个注解的目的主要是为了区分MVC中每个类的区别。

    @Scope

    使用注解注册Bean 默认的作用域还是singleton,可以使用@Scope("prototype")改变对象作用域

    @Value

    在使用注解给对象注入值的时候,不再需要Get/Set方法

    基础类型

    使用@Value注解

    @Value("小明")

    private String name;

     

    对象引用

    @Autowired

    private Pet MyPet;

    使用@Autowired注解

    默认是ByType的,如果需要ByName需要配合@Qualifier注解

    @Autowired()

    @Qualifier("p2")

    private Pet MyPet;

     

    面向切面编程 代码增强 

    AOP(Aspect Oriented Programming)面向切面编程。

    面向切面,是与OOP(Object Oriented Programming)面向对象编程并列的编程思想。

    Spring支持两种方法,那么我们在使用spring进行动态代理时究竟使用的哪一种方法呢?spring优先支持实现接口的方式,如果没有接口则使用cglib方式

    代理 

    通过代理可以隐藏目标类的具体实现;在不修改目标类代码的情况下能够对其功能进行增强。

    l 委托类和代理类有相同的接口或者共同的父类

    代理类为委托类负责处理消息,并将消息转发给委托类

    委托类和代理类对象通常存在关联关系

    一个代理类对象与一个委托类对象关联

    代理类本身并不是真正的实现者!而是通过调用委托类的方法来实现功能!

    静态代理

    使用硬编码的方式增强原有方法

    l 优点:可以做到不对目标对象进行修改的前提下,对目标对象进行功能的扩展和拦截。

    l 缺点:因为代理对象,需要实现与目标对象一样的接口,会导致代理类十分繁多,不易维护,同时一旦接口增加方法,则目标对象和代理类都需要维护。

    Girl -> 目标对象 -> 被包装/增强的对象

    public class Girl implements Human{
    
    public void eat() {
    
    System.out.println("Em mmm.. mm..");
    
    }
    
    }

    抽象接口

    interface Human {
    
    public void eat();
    
    }

    ProxyGirl 代理对象,包含对原对象方法的增强,通过构造方法传入原对象,并实现和原对象相同的接口,实现接口方法,便可以利用Java多态的特性,通过访问代理方法同时能够调起原对象的实现,并对其增强。

    public class ProxyGirl implements Human {
    
     
    
    private Human human;
    
     
    
    public ProxyGirl() {
    
    super();
    
    }
    
     
    
    public ProxyGirl(Human human) {
    
    super();
    
    this.human = human;
    
    }
    
     
    
    public void eat() {
    
    System.out.println("chiqian");
    
    human.eat();
    
    System.out.println("chihou");
    
    }
    
    }

    测试类

    Girl girl = new Girl();
    
     
    
    Human proxyGirl = new ProxyGirl(girl);
    
    proxyGirl.eat();

    动态代理

    动态代理是指动态的在内存中构建代理对象(需要我们制定要代理的目标对象实现的接口类型),即利用JDKAPI生成指定接口的对象,也称之为JDK代理或者接口代理。

    目标对象实现了接口 JDK动态代理

    目标对象没有实现口CGLib

     

    JDK动态代理

    CGLIB动态代理

    底层ASM

  • 相关阅读:
    UVA1349 Optimal Bus Route Design 最优巴士路线设计
    POJ3565 Ants 蚂蚁(NEERC 2008)
    UVA1663 Purifying Machine 净化器
    UVa11996 Jewel Magic 魔法珠宝
    NEERC2003 Jurassic Remains 侏罗纪
    UVA11895 Honorary Tickets
    gdb调试coredump(使用篇)
    使用 MegaCLI 检测磁盘状态并更换磁盘
    员工直接坦诚直来直去 真性情
    山东浪潮超越3B4000申泰RM5120-L
  • 原文地址:https://www.cnblogs.com/littlepage/p/11018921.html
Copyright © 2011-2022 走看看