Spring 从入门到精通 (十七) AOP底层如何加工创建代理对象

举报
周棋洛 发表于 2022/07/26 22:20:33 2022/07/26
【摘要】 关键词:Spring | AOP | 创建对象 | 底层 本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨ 目录 ...

关键词:Spring | AOP | 创建对象 | 底层

本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨

在这里插入图片描述

一、疑问?

为什么通过原始对象的 id 值从工厂拿实例,得到的却是代理对象?

二、一张图

在这里插入图片描述

三、编码

新建空maven项目,包目录结构如下:

在这里插入图片描述

依赖坐标 pom.xml

所需依赖如下:

<dependencies>
    <!--Spring Container Core-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.10.RELEASE</version>
    </dependency>
    <!--Spring AOP-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.1.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.8.8</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.3</version>
    </dependency>
    <!--Lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
    <!--单元测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

实体类 User

实体类使用了效率插件 Lombok

@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
    private String name;
    private String pwd1;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

UserService 接口

业务层接口定义了简简单单两个方法

public interface UserService {
    void login(String name, String pwd1);
    void register(User user);
}

  
 
  • 1
  • 2
  • 3
  • 4

接口实现类 UserServiceImpl

实现业务层接口,此时的业务专心做自己的核心业务

public interface UserService {
    void login(String name, String pwd1);
    void register(User user);
}

  
 
  • 1
  • 2
  • 3
  • 4

工厂配置业务层 bean

在工厂中配置,业务层的 bean,交由容器管理

<bean id="userService" class="com.liu.service.UserServiceImpl"/>

  
 
  • 1

ProxyBeanPostProcessor 核心

实现 BeanPostProcessor 在 bean 对象返回前进行一次再加工,怎么加工自己写,这里就使用之前学习的JDK动态代理,因为业务类实现了接口,创建响应的动态代理类对象

注意: 参数中的 Object bean 就是原始对象,在使用JDK创建代理类对象的时候,因为没有自己的类加载器,所以第一个参数随便借一个类加载器,第二个参数原始对象实现的接口,这样代理类对象才知道该区实现哪个接口,我们通过 Object bean 就可以获得,第三个参数写自己的附加操作,同时执行目标方法。

public class ProxyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("工厂加工了,拿到返回了代理对象");
                Object invoke = method.invoke(bean, args);
                return invoke;
            }
        };
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),
                bean.getClass().getInterfaces(),
                handler);
        return userServiceProxy;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

工厂配置

<bean id="proxyBeanPostProcessor" class="com.liu.factory.ProxyBeanPostProcessor"/>

  
 
  • 1

Test 测试

编写测试类,去工厂中通过id userService 拿对象时,因为对象在返回时,被加工了,加工过程就是通过原始对象使用JDK动态代理技术创建出了动态代理类对象,并作为返回值返回,这也就是为什么通过 userService 拿到的是代理对象,而不是原始对象

@Test
public void t1(){
    ApplicationContext con = new ClassPathXmlApplicationContext("/spring.xml");
    UserService userService = (UserService) con.getBean("userService");
    userService.login("asd", "asda");
    userService.register(new User());
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果:

工厂加工了,拿到返回了代理对象
处理核心业务用户登录,并调用DAO~~~~
工厂加工了,拿到返回了代理对象
处理核心业务用户注册,并调用DAO~~~~

  
 
  • 1
  • 2
  • 3
  • 4

四、写在最后

座右铭:不要在乎别人如何看你,要在乎你自己如何看未来,看梦想,看世界…!

一起学习的可以私信博主或添加博主微信哦。

专栏:订阅专栏 ✅
关注:关注博主 🆙

文章来源: blog.csdn.net,作者:王子周棋洛,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/m0_53321320/article/details/125988715

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。