一、 DI 注解
- Spring的@Autowired
- JavaEE的@Resource
都是取代注入bean, 贴类中setter 方法或者字段上(完成属性或字段的注入,注入是 bean,取代 XML property ref 元素)
- 可以让 Spring 自动的把属性或字段需要的对象找出来,并注入到属性上或字段上。
- 可以贴在字段或者 setter 方法上面。
二、 IoC 注解
让Spring简化配置bean
- 四个注解的功能是相同的,用来让Spring帮我们创建对象,只是用于标注不同类型的类上。
@Repository:用于标注数据访问组件,即DAO实现类上。
@Service:用于标注业务层实现类上。
@Controller:用于标注控制层类上(如SpringMVC的Controller)。
@Component:当不是以上的话,可以使用这个注解进行标注。
在 spring 配置文件中配置第三方解析程序 <context:component-scan base-package="使用上面这些注解的类所在包"/>
image.png
注意:@Component 不写 value 值的话,bean 名字就类名首字母小写,上面列子就是 bean 的名字就是 person。
三、 bean的作用域、初始化、销毁注解
@Scope: 贴在类上,标明 bean 的作用域。
@PostConstruct: 贴在方法上,标明 bean 创建完后调用此方法。
@PreDestroy : 贴在方法上,标明容器销毁时调用此方法。
四、 applicationContext.xml
image.png五、 代理模式
解决事务的繁琐
- 客户端直接使用的都是代理对象,不知道真实对象是谁,此时代理对象可以在客户端和真实对象之间起到中介的作用。
- 代理对象完全包含真实对象,客户端使用的都是代理对象的方法,和真实对象没有直接关系;
- 代理模式的职责:把不是真实对象该做的事情从真实对象上撇开—职责分离。
分类
- 静态代理:在程序运行前就已经存在代理类的字节码文件,代理对象和真实对象的关系在运行前就确定了。(即代理类及对象要我们自己创建)
- 动态代理:代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件,动态生成字节码对象,代理对象和真实对象的关系是在程序运行时期才确定的。(即代理类及对象不要我们自己创建)
动态代理实现方式:
1.针对真实类有接口使用 JDK 动态代理;
2.针对真实类没实现接口使用CGLIB或Javassist组件。
六、静态代理
-
解决代码责任不分离的问题,真实对象隐藏起来了,保护真实对象。(不在容器里了)
缺点:项目的变大,代理类太多
七、JDK动态代理
- 解决静态代理的问题,不需手动地提供那么多代理类
缺点:api难用,配置Spring麻烦
动态代理API
- java.lang.reflect.Proxy类
Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
主要方法:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler hanlder)
方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例
参数:
loader :类加载器,一般传递真实对象的类加载器
interfaces:代理类需要实现的接口
handler:代理执行处理器,说人话就是生成代理对象帮你要做什么
返回:创建的代理对象
- java.lang.reflect.InvocationHandler 接口
主要方法:public Object invoke(Object proxy, Method method, Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用,让使用者自定义做什么事情, 对原来方法增强(加什么功能)。
参数:
proxy :生成的代理对象
method:当前调用的真实方法对象
args :当前调用方法的实参
返回:真实方法的返回结果
主要方法:public Object invoke(Object proxy, Method method, Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用,让使用者自定义做什么事情, 对原来方法增强(加什么功能)。
参数:
proxy :生成的代理对象
method:当前调用的真实方法对象
args :当前调用方法的实参
返回:真实方法的返回结果
要使用 JDK 动态代理,真实类必须实现接口
类体系及调用流程
image.png八、CGLIB动态代理
区别:与JDK动态代理不同的是,其真实类不用实现接口,生成代理类的代码不一样且代理类会继承真实类。
动态代理API
- org.springframework.cglib.proxy.Enhancer
类似JDK中Proxy,用来生成代理类创建代理对象的。 - org.springframework.cglib.proxy.InvocationHandler
类似JDK中InvocationHandler,让使用者自定义做什么事情,对原来方法增强。
实现
-
修改 TransactionHandler 实现 org.springframework.cglib.proxy.InvocationHandler 接口
-
修改单元测试类中的测试方法,改用 Enhancer 来生成代理类创建代理对象的
类体系及调用流程
image.png九、 动态代理选用
- JDK 动态代理是基于实现接口的,CGLIB 和 Javassit 是基于继承委托类的。
从性能上考虑:Javassit > CGLIB > JDK。 - 若真实类实现了接口,优先选用 JDK 动态代理。(因为会产生更加松耦合的系统,也更符合面向接口编程)
- 若真实类没有实现任何接口,使用 Javassit 和 CGLIB 动态代理。
网友评论