Java Design Pattern(2)
一. Factory (Spring Bean Creation)
在Spring中,构成应用程序主干并由Spring IoC 容器管理的对象称为bean。bean是一个由Spring IoC容器实例化,组装和管理的对象。否则,bean只是应用程序中许多对象之一。Bean及其之间的依赖关系反映在容器使用的配置元数据中。
Bean定义包含称为配置元数据的信息,容器需要知道以下内容 -
-
- 如何创建一个bean
- Bean的生命周期细节
- Bean的依赖关系
Spring配置元数据
Spring IoC容器与实际编写此配置元数据的格式完全分离。以下是为Spring容器提供配置元数据的三种重要方法 -
-
- 基于XML的配置文件。
- 基于注释的配置
- 基于Java的配置
Spring创建Bean的大致过程
- 实例化BeanFactoryPostProcessor实现类
- 调用BeanFactoryPostProcessor#postProcessBeanFactory
- 实例化BeanPostProcessor实现类
- 调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
- 实例化Bean
- 调用InstantiationAwareBeanProcessor#postProcessAfterInstantiation
- 调用InstantiationAwareBeanPostProcessor#postProcessPropertyValues
- 为Bean注入属性
- 调用BeanNameAware#setBeanName
- 调用BeanClassLoaderAware#setBeanClassLoader
- 调用BeanFactoryAware#setBeanFactory
- 调用BeanPostProcessor#postProcessBeforeInitialization
- 调用InitializingBean#afterPropertiesSet
- 调用Bean的init-method
- 调用BeanPostProcessor#postProcessAfterInitialization
参考:https://www.cnblogs.com/micrari/p/7354650.html
二.Singleton
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
-
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
单例模式的几种实现方式
单例模式的实现有多种方式,如下所示:
1、懒汉式,线程不安全
是否 Lazy 初始化:是
是否多线程安全:否
实现难度:易
描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
2、懒汉式,线程安全
是否 Lazy 初始化:是
是否多线程安全:是
实现难度:易
描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。
3、饿汉式
是否 Lazy 初始化:否
是否多线程安全:是
实现难度:易
描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口
语法:
//Create object to be proxied Student student = new Student(); //Create the Proxy Factory AspectJProxyFactory proxyFactory = new AspectJProxyFactory(student); //Add Aspect class to the factory proxyFactory.addAspect(Logging.class); //Get the proxy object Student proxyStudent = proxyFactory.getProxy(); //Invoke the proxied method. proxyStudent.getAge();
Logging.java package com.tutorialspoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.PointCut; import org.aspectj.lang.annotation.Before; @Aspect public class Logging { /** Following is the definition for a PointCut to select * all the methods available. So advice will be called * for all the methods. */ @PointCut("execution(* com.tutorialspoint.Student.getAge(..))") private void selectGetAge(){} /** * This is the method which I would like to execute * before a selected method execution. */ @Before("selectGetAge()") public void beforeAdvice(){ System.out.println("Going to setup student profile."); }
Student.java package com.tutorialspoint; public class Student { private Integer age; public void setAge(Integer age) { this.age = age; } public Integer getAge() { System.out.println("Age : " + age ); return age; } }
MainApp.java package com.tutorialspoint; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); Student student = (Student) context.getBean("student"); //Create the Proxy Factory AspectJProxyFactory proxyFactory = new AspectJProxyFactory(student); //Add Aspect class to the factory proxyFactory.addAspect(Logging.class); //Get the proxy object Student proxyStudent = proxyFactory.getProxy(); //Invoke the proxied method. proxyStudent.getAge(); } }
Beans.xml <?xml version = "1.0" encoding = "UTF-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:aop = "http://www.springframework.org/schema/aop" xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "> <!-- Definition for student bean --> <bean id = "student" class = "com.tutorialspoint.Student"> <property name = "age" value = "11"/> </bean> <!-- Definition for logging aspect --> <bean id = "logging" class = "com.tutorialspoint.Logging"/> </beans>