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
- 点赞
- 收藏
- 关注作者
评论(0)