让你知道一下你在哪个容器里面
04 - ApplicationContextAware - setApplicationContext - org.springframework.context.support.ClassPathXmlApplicationContext@14acaea5, started on Fri Aug 21 21:14:50 CST 2020
初始化方法调用之前调用
05 - BeanPostProcessor - postProcessBeforeInitialization - userService
构造、注入完毕之后调用1(初始化,加载资源)
06 - InitializingBean - afterPropertiesSet
构造、注入完毕之后调用2(初始化,加载资源)
07 - init-method
初始化方法调用之后调用
08 - BeanPostProcessor - postProcessAfterInitialization - userService
业务方法
09 - UserServiceImpl - login - 123_456
销毁之前调用1(释放资源)
10 - DisposableBean - destroy
销毁之前调用2(释放资源)
11 - destroy-method
[](https://gitee.com/vip204888/java-p7)代理
=====================================================================
> [【Spring AOP】静态代理设计模式、Spring 动态代理开发详解、切入点详解(切入点表达式、切入点函数)](https://gitee.com/vip204888/java-p7)
[](https://gitee.com/vip204888/java-p7)业务层的一些问题
---------------------------------------------------------------------------
业务层(Service)的主要内容:
* 业务代码:业务运算、dao 操作等(**必要**)
* 附加代码:事务、日志、性能监控、异常处理等(可选)
![在这里插入图片描述](https://img-blog.csdnimg.cn/4674ad0f5b134ea5bbc588c8f1b79a9c.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_1,color_FFFFFF,t_70)
现在的尴尬情况:
* 在业务层加入附加代码会显得很臃肿、累赘
* 但很多时候又好像不得不加
* * *
类比到生活中的一些问题可以更好的理解:
* 房东只需要做自己必须要做的事情,其余事情交给中介(代理)去做
![在这里插入图片描述](https://img-blog.csdnimg.cn/cbae8b00c79a4837b44e8f564a8fbe03.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_1,color_FFFFFF,t_70)
对于程序开发而言:
* 业务层只需要处理好业务代码,其余的事情交给代理去做
![在这里插入图片描述](https://img-blog.csdnimg.cn/080fe7e49db44486b035abd295610f7b.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_1,color_FFFFFF,t_70)
* * *
代理的作用:在不修改目标类的目标方法代码的前提下,为目标方法增加额外功能
代理类中必须也有同样的目标方法
* 代理类实现跟目标类同样的接口
* 若目标类没有实现接口,代理类继承目标类
代理的实现方案:
* **静态代理 (Static Proxy)**
开发人员需要手动编写代理类(创建对应的 \*.java 文件)
基本上,一个目标类就需要编写一个代理类
* **动态代理 (Dynamic Proxy)**:**程序运行过程中动态生成代理类的字节码**
[](https://gitee.com/vip204888/java-p7)静态代理 (Static Proxy)
--------------------------------------------------------------------------------------
示例代码:[静态代理](https://gitee.com/vip204888/java-p7)
要代理 UserServiceImpl,需要实现 UserService 接口(或者继承目标类):
// 代理类实现跟目标类同样的接口
public class UserServiceProxy implements UserService {
private UserService target;
// 为基于setter的注入提供条件
public void setTarget(UserService target) {
this.target = target;
}
@Override
public boolean login(String username, String password) {
// 额外操作
System.out.println("日志------------------1");
// 调用目标类的方法实现
boolean result = target.login(username, password);
// 额外操作
System.out.println("日志------------------2");
return result;
}
}
// 代理类继承目标类, 也可实现静态代理
public class SkillServiceProxy extends SkillService {
private SkillService target;
public void setTarget(SkillService target) {
this.target = target;
}
@Override
public boolean save(Object skill) {
System.out.println("SkillServiceProxy - 1");
boolean result = target.save(skill);
System.out.println("SkillServiceProxy - 2");
return result;
}
}
<bean id=“userService”
class="com.mj.proxy.UserServiceProxy">
<property name="target">
<bean class="com.mj.service.impl.UserServiceImpl"/>
</property>
<bean id=“skillService”
class="com.mj.proxy.SkillServiceProxy">
<property name="target">
<bean class="com.mj.service.SkillService"/>
</property>
[](https://gitee.com/vip204888/java-p7)动态代理 (Dynamic Proxy)
---------------------------------------------------------------------------------------
动态代理的常见实现方案有 2 种:
1. **JDK 自带**:代理类需要实现和目标类一样的接口
2. **开源项目 CGLib** (Code Generation Library):代理类继承目标类
> Spring 已经集成了 CGLib
示例代码:[Spring - 动态代理](https://gitee.com/vip204888/java-p7)
由我们手动实现代理,需要和前面所讲的 Spring 生命周期 BeanPostProcessor 结合起来,拦截每一个 bean 的生命周期,从而实现对每一个 bean 的代理(可以通过判断类名、方法等,来指定哪些对象需要代理)
### [](https://gitee.com/vip204888/java-p7)JDK 动态代理 - Proxy.newProxyInstance
/**
- 实现BeanPostProcessor接口会拦截每一个bean的生命周期
*/
public class LogProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {
// 初始化方法调用前不做任何处理
return bean;
}
@Override
public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {
return Proxy.newProxyInstance(
getClass().getClassLoader(), // 类加载器
target.getClass().getInterfaces(), // 代理类需要实现的接口(目标类的接口)
new LogInvocationHandler(target)); // 附加代码
}
private static class LogInvocationHandler implements InvocationHandler {
笔者福利
以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。
有了这个,面试踩雷?不存在的!
需要这套“面试宝典”的,点击这里即可免费获取!回馈粉丝,诚意满满!!!
ocationHandler implements InvocationHandler {
笔者福利
以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。
有了这个,面试踩雷?不存在的!
需要这套“面试宝典”的,点击这里即可免费获取!回馈粉丝,诚意满满!!!
[外链图片转存中…(img-8u19Umfy-1628596977019)]
[外链图片转存中…(img-3R8bgywe-1628596977021)]
[外链图片转存中…(img-xfurqa7L-1628596977023)]