80.【Spring5】(五)

简介: 80.【Spring5】

2.详细讲解

  1. 配置类
  2. @Configuration: 代表这是一个配置类,和我们之前看的beans.xml一样
  3. @Bean:注册一个bean,就相当于我们之前写的bean标签,这个方法的名字相当于bean标签的id属性。方法的返回值就相当于bean中的class属性
  4. @ComponentScan(“Com.Jsxs.pojo”) 扫描包
  5. @Import(JsxsConfig2.class) 导入包
  6. 实体类
  7. @Component: 这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中;表名一个类作为组件类,并告知Spring要为这个类创建bean
  8. 测试类
  9. 如果我们完全使用了配置类方式去做,我们就只能通过 ACAC 进行获取

3.小结

这种纯java的配置方式,在SpringBoot中随处可见!

(十一)、注解(总结)

  1. @SuppressWarnings(“all”) ====》镇压警告(方法和类上都可以)
  2. @Override ====》重写的注解 (方法上)
  3. @Target ====》注解的作用域 (方法 字段 类)
  4. @Target(value = {ElementType.METHOD}) //设置的只能在方法上使用
  5. @Retention 注解运行状态
  6. @Retention(value = RetentionPolicy.RUNTIME) //跑动的时候有效
  7. @Documented ====》 是否生成JavaDoc
  8. @Inherited ====》 是否进行子类继承父类
  9. @interface ====》自定义的注解

(十二)、代理模式

1.为什么要使用代理模式?

因为这就是SpringAop的底层;

  • 静态代理
  • 动态代理

2.静态代理

  • 抽象角色: 一般会使用接口和抽象类来解决(租房子这个事情)
  • 真实角色:被代理的角色(房东或则客户)
  • 代理角色:代理真是对象,代理真实角色后,我们一般会做一些附属操作。(中介)
  • 客户:访问代理角色的人
    静态代理: 代理对象和被代理对象都要实现接口,然后代理对象可以扩展功能。
(1).客户租房子案列

房东想出租一套房子,但是只想把钥匙给它,其他的什么事情都不想做。于是乎房东想到了中介可以帮助我们完成这些事情,然后就去找中介进行办理了手续。于是乎: 中介也了解房东的心思,不想管那么多的事情,于是就让房东交出房子的钥匙(rent)和身份证信息(host),然后就让房东走了。然后此时此刻有一个客户(cilent)找到了中介(proxy),在中介的介绍下,客户选择了房东名字叫做Host的这个房子,于是找代理进行办理,

接口

package com.Jsxs.demo1;
//出租房子这件事
public interface rent {
    void rent();
}

房东1

package com.Jsxs.demo1;
public class Host implements rent{
    @Override
    public void rent() {
        System.out.println("房东: 我要出租房子");
    }
}

中介

package com.Jsxs.demo1;
// 房东先拉过来 打一架;然后再继承房东的房子
public class proxy  implements rent{
    /*
        中介下面有很多的房东,然后中介只要调用出租房子这个接口,然后调取某个房东的房子去出租
     */
    private Host host;  //房东1
    public proxy() {
    }
    public proxy(Host host) {
        this.host = host;
    }
    @Override
    public void rent() {
        host.rent();
        this.fare();
        this.regular();
    }
//    中介扩展
    public void fare(){
        System.out.println("中介收取费用");
    }
    public void regular(){
        System.out.println("中介签合同");
    }
}

客户

package com.Jsxs.demo1;
// 客人 :  租房子
public class Client {
    public static void main(String[] args) {
//    第一套方案 : 无中介直接找厂家
        Host host = new Host();
        host.rent();
//    第二套方案 : 不找房东 找中介
        proxy proxy = new proxy(host);
        proxy.rent();
    }
}

(2).代理模式的好处
  • 可以使真实角色的操作更加存粹! 不用去关注一些公共的事务
  • 公共也就是交给代理角色,实现业务的分工
  • 公共业务发生扩展的时候,方便集中管理!
(3).代理模式的缺点
  • 一个真实角色就会产生一个代理角色;代码量会进行翻倍·开发效率会变低。
    为什么说 一个真实角色就会产生一个代理对象? 是因为我们在中介(proxy)类中,只能设置一个房东,如果设置两个房东,那么我们的(proxy)构造函数要同时写两个房东的信息,然而客户只会选择一套房子进行操作,所以不能一个代理做两个房东的生意.
(4).代理模式真实案列

我们此次的实验是: 我们通过客户(Client)类,实现对实际业务的需求。我们这次要求在每次运行的时候都要进行添加日志的操作! 不要轻易改变公司的原有结构代码,因为接口不只是你在用,运用代理模式这样可以分工操作,所以我们不能对原有结构进行修改。

UserServic接口

package com.Jsxs.demo2;
public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

UserServic接口实现类

package com.Jsxs.demo2;
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }
    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }
    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }
    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
}

客户类(实现)

package com.Jsxs.demo2;
public class Cilent {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserProxy userProxy = new UserProxy(userService);
        userProxy.add();
    }
}

代理类

package com.Jsxs.demo2;
public class UserProxy implements UserService{
    private UserService userService;
    public UserProxy(UserService userService) {
        this.userService = userService;
    }
    public UserProxy() {
    }
    @Override
    public void add() {
        log("add");
        userService.add();
    }
    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }
    @Override
    public void update() {
        log("update");
        userService.update();
    }
    @Override
    public void query() {
        log("query");
        userService.query();
    }
    public void log(String msg){
        System.out.println("【Debug】"+"使用了"+msg+"方法");
    }
}

3.动态代理(代理的是接口)

  • 动态代理和静态代理角色一样
  • 动态代理类是动态生成的,不是我们自己手动写的。
  • 动态代理分为两类: 基于接口的动态代理,基于类的动态代理
  1. 基于接口 : JDK动态代理【我们在这里使用】
  2. 基于类 : cglib
  3. Java字节码 : javasist
1.环境搭配
(1).需要了解两个类

Proxy : 代理

InvocationHandler : 调用处理程序

InvocationHandler是由代理实例的调用处理程序实现的接口 。 每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法

(2).动态代理的好处
  • 可以使真实角色的操作更加存粹! 不用去关注一些公共的事务
  • 公共也就是交给代理角色,实现业务的分工
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个 动态 代理类的是一个接口,一般对应的就是一类业务
  • 一个动态代理类 可以代替多个类,只要实现了同一个接口
(3).非完全动态代理

我是房东: 我想向外面租房子。想找个中介帮忙进行处理这件事情。

接口

package com.Jsxs.demo3;
//出租房子这件事
public interface rent {
    void rent();
}

房东实现接口

package com.Jsxs.demo3;
public class Host implements rent {
    @Override
    public void rent() {
        System.out.println("房东1: 我要向外出租房子");
    }
}

自动生成代理类

(1).我们在这里继承: 调用处理程序这个接口(InvocationHandler)
(2).创建真实对象(被代理对象)
(3).生成得到代理类:  类加载器;被代理对象的接口;调用处理程序;
Proxy.newProxyInstance(this.getClass().getClassLoader(),rent1.getClass().getInterfaces(),this);
(4).重写(InvocationHandler)接口的方法
(5).在重写的方法里面写: 目的是进行代理执行
 Object invoke = method.invoke(rent1, args);
package com.Jsxs.demo3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
    我们用这个类,自动生成代理类
 */
public class proxyInvocationHandler implements InvocationHandler {
    private rent rent1;
    public void setRent1(rent rent1) {
        this.rent1 = rent1;
    }
    //    生成得到代理类
    public Object getPoxy(){
//        类加载器 ==》接口 ===》 InvocationHandler
        return  Proxy.newProxyInstance(this.getClass().getClassLoader(),rent1.getClass().getInterfaces(),this);
    }
//  处理代理实列,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
//        动态代理的实质就是使用反射机制
        Object invoke = method.invoke(rent1, args);
        write();
        return null;
    }
    public void seeHouse(){
        System.out.println("看房");
    }
    public void write(){
        System.out.println("签合同");
    }
}

客户类(实现类)

(1).创建真实对象(被代理对象)
(2).创建代理类
(3).向代理类里面写入被代理对象
(4).获取代理类; 强制类型转换成(接口的类型,不是接口的实现类)
package com.Jsxs.demo3;
public class Client {
    public static void main(String[] args) {
//真实对象
        Host host = new Host();
//代理角色 : 现在没有
        proxyInvocationHandler pih = new proxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
        pih.setRent1(host);
        rent poxy = (rent) pih.getPoxy();  //这里的proxy就是动态生成的,我们没有写
        poxy.rent();
    }
}

(4).完全动态代理

只需要做出一些改变,就是引入被代理对象的时候,我们不进行指定的类型,而直接写出Object的类型就可以。

万能

package com.Jsxs.demo4;
import com.Jsxs.demo3.rent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
    我们用这个类,自动生成代理类
 */
public class proxyInvocationHandler implements InvocationHandler {
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    //    生成得到代理类
    public Object getPoxy(){
//        类加载器 ==》接口 ===》 InvocationHandler
        return  Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
//  处理代理实列,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        动态代理的实质就是使用反射机制
        Object invoke = method.invoke(target, args);
        return null;
    }
}

客户

package com.Jsxs.demo4;
import com.Jsxs.demo2.UserService;
import com.Jsxs.demo2.UserServiceImpl;
public class Client {
    public static void main(String[] args) {
//        真实角色
        UserServiceImpl userService = new UserServiceImpl();
//        代理角色,不存在
        proxyInvocationHandler handler = new proxyInvocationHandler();
//        要动态处理的对象
        handler.setTarget(userService);
//        动态生成代理类
        UserService poxy = (UserService) handler.getPoxy();
        poxy.add();
    }
}

(5).总结

静态代理和动态代理的区别: 就是我们在中介类(代理类)的时候继承的东西不一样,静态代理类继承的接口是(被代理对象的接口类),动态代理类继承的是调用程序处理类(InvocationHandler)

相关文章
|
1月前
|
Java 应用服务中间件 Maven
Spring
Spring
|
5月前
|
XML Java 数据库
|
6月前
|
存储 设计模式 Java
【Spring】——Spring简单 读和取(二)
【Spring】——Spring简单 读和取
64 0
【Spring】——Spring简单 读和取(二)
|
6月前
|
Java 程序员 Maven
Spring(上)
Spring(上)
40 0
|
XML Java 数据格式
|
存储 XML Java
|
XML 前端开发 Java
Spring(一)
Spring(一)
109 0
Spring(一)
|
Java 索引 Spring
|
缓存 安全 Java
Spring详解【下】
1、Spring 1.1、简介 Spring:春天 >给软件行业带来了春天! 2002,首次推出了Spring框架的雏形:interface21框架! Spring框架即以interface21框架为基础,经过重新的设计,并不断的丰富其内涵,于2004年3月24日,发布了1.0正式版。 Rod Jo
|
Java 程序员 Spring
深入理解 Spring finishBeanFactoryInitialization (二)
深入理解 Spring finishBeanFactoryInitialization (二)
137 0