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

举报
周棋洛 发表于 2022/07/26 22:20:33 2022/07/26
5.9k+ 0 0
【摘要】 关键词: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>

  
 

实体类 User

实体类使用了效率插件 Lombok

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

  
 

UserService 接口

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

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

  
 

接口实现类 UserServiceImpl

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

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

  
 

工厂配置业务层 bean

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

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

  
 

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;
    }
}

  
 

工厂配置

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

  
 

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());
}

  
 

结果:

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

  
 

四、写在最后

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

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

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

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

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

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

作者其他文章

评论(0

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

    全部回复

    上滑加载中

    设置昵称

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

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

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