Java 六大设计原则;Java 23种设计模式(在此介绍三种设计模式)
Java设计模式
单例模式
应用场景:spring中bean的作用域用的就是单例模式
//基本的单例模式————懒汉式
public class student {
//3.创建static修饰的成员变量
private static student stu;
//1.设计私有构造方法
private student() {
}
//2.提供一个共有的方法
public static synchronized student getInstance(){
if (stu == null){
stu = new student();
}
return stu;
}
}
//基本的单例模式————饿汉式
public class student {
//3.创建static修饰的成员变量
private static student stu = new student();
//1.设计私有构造方法
private student() {
}
//2.提供一个共有的方法
public static synchronized student getInstance(){
return stu;
}
}
/*
饿汉式与懒汉式的不同是:创建对象的时间点不同
*/
//测试类
student stu1 = student.getInstance();
student stu2 = student.getInstance();
System.out.println(stu1 == stu2);
工厂模式
//工厂类
public class NoodleFactory {
//定义静态常量的标识————规定下面条的类型
public static final int NOODLE_BIA = 1;
public static final int NOODLE_REGAN = 2;
public static final int NOODLE_LANZHOU = 3;
//创建不同类型的面条
public static INoodles getNoodle(int type) {
if (type == 1) {
return new BiaBiaMianImp();
}else if(type == 2){
return new ReGanMianImp();
}else if(type == 3){
return new LanzhouLaMianImp();
}
return null;
}
}
//测试类
public class Test01 {
public static void main(String[] args) {
//方式1
NoodleFactory.getNoodle(2).noodleType();
//方式2
NoodleFactory.getNoodle(NoodleFactory.NOODLE_REGAN).noodleType();
}
}
//自定义接口及实现类
public interface INoodles {
public void noodleType();
}
public class BiaBiaMianImp implements INoodles{
@Override
public void noodleType() {
System.out.println("----来一碗边个边个面---");
}
}
public class LanzhouLaMianImp implements INoodles{
@Override
public void noodleType() {
System.out.println("-----来一碗兰州拉面----");
}
}
public class ReGanMianImp implements INoodles{
@Override
public void noodleType() {
System.out.println("----来一碗武汉热干面----");
}
}
代理模式
功能:中间隔离;方法增强
静态代理
- 是由程序员创建或特定工具自动生成源代码,在对其编译。
- 在程序员运行之前,代理类.class文件就已经被创建了。
//自定义接口
public interface IWomen {
public void makeEyeWithMan();
}
//被代理对象
public class PanJinLianImp implements IWomen{
@Override
public void makeEyeWithMan() {
System.out.println("给ximenqing抛媚眼");
}
}
//代理
public class WangPoImp implements IWomen{
//被代理对象
IWomen obj;
//构造方法给属性赋值
public WangPoImp(IWomen obj) {
this.obj = obj;
}
@Override
public void makeEyeWithMan() {
System.out.println("镇壶酒,搞点气氛");
obj.makeEyeWithMan();
}
}
//测试类
public class XiMenTest {
public static void main(String[] args) {
//1.创建被代理对象
IWomen pan = new PanJinLianImp();
//2.创建代理
IWomen wang = new WangPoImp(pan);
wang.makeEyeWithMan();
}
}
动态代理
- 在程序运行时通过反射机制动态创建的。
- 动态代理分为: 基于接口的动态代理(jdk自带);基于子类的动态代理(第三方)
基于接口的动态代理(jdk自带)
//自定义接口
public interface ISinger {
public void sing();
public int dance(int num);
}
//被代理
public class JinXingImp implements ISinger{
@Override
public void sing() {
System.out.println("----有点甜---");
}
@Override
public int dance(int num) {
System.out.println("---哈哈哈哈----");
return 0;
}
}
//jdk动态代理测试
public class Test01 {
public static void main(String[] args) {
//1.创建被代理对象
final ISinger jin = new JinXingImp();
//2.创建代理对象
final ISinger daiLi = (ISinger) Proxy.newProxyInstance(jin.getClass().getClassLoader(), jin.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("------自我介绍-----");
Object obj = method.invoke(jin, args);
return obj;
}
});
daiLi.sing();
daiLi.dance(6);
}
}
基于子类的动态代理(第三方)
//自定义接口
public interface ISinger {
public void sing();
public int dance(int num);
}
//实现接口的类
public class TengImp implements ISinger{
@Override
public void sing() {
System.out.println("听了赵雷的成都去了成都,听了汪峰的北京去了北京,至今不敢听腾格尔的天堂");
}
@Override
public int dance(int num) {
System.out.println("学武术,跳舞");
return 0;
}
}
//cglib动态代理测试
public class Test02 {
public static void main(String[] args) {
//1.创建被代理对象
final ISinger teng = new TengImp();
//2.创建代理对象
ISinger dai = (ISinger) Enhancer.create(teng.getClass(), teng.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Object obj = method.invoke(teng,objects);
return obj;
}
});
dai.sing();
dai.dance(6);
}
}
用动态代理的优化转账业务的案例见资源
AOP(面向切面编程)
AOP概述
将那些与业务无关,却为业务模块所共同调用的逻辑(例如:事务管理、日志管理、控制权限等)封装抽取成一个可重用的模块,这个模块被命名为"切面(Aspect)",便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性
Spring AOP 基于动态代理实现
- 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);
- 如果被代理的对象,没有实现某个接口,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类)
AOP相关概念
AOP通知类型
AOP将抽取出来的共性功能称为通知;通知类型:以通知在上下文中的具体位置作为划分
前置通知(Before)
返回通知(After-returning)
异常通知(After-throwing)
后置通知(After)
环绕通知(Around)
AOP连接点(Join point)
AOP将所有的方法都视为连接点,不管是接口里面的抽象方法,还是实现类里面的重写方法,都是连接点
AOP切点(Pointcut)
AOP将可能被抽取共性功能的方法称为切入点。切入点是连接点的子集
AOP目标对象(Target)
就是挖掉功能的方法对应的类生的对象,这种对象是无法直接完成最终工作的
AOP织入(Weaving)
是将挖掉的功能回填的动态过程
AOP切面
切点+通知
SpringAOP+AspectJ实现步骤
1.添加依赖,aop与aspectj表达式的依赖
2.创建spring的主配置文件,bean内的命名空间要添加aop的
3.创建业务代码并编写日志记录代码(事务管理代码)
4.将业务层与日志记录层注入spring容器
5.<aop:config>--aop配置 aop:aspect--aop切面 aop:before--通知内容与通知类型
切点表达式配置语法
execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))
eg: execution(public void com.apesource.service.ServiceImp.findAll())
- 1.修饰符可以省略代表任意 execution(返回值 包名称.类名称.方法名称(参数列表))
- 2.返回值可以使用“*”代表任意 execution(* 包名称.类名称.方法名称(参数列表))
- 3.包名可以使用“*”代表任意名称 execution(* *.*.*.类名称.方法名称(参数列表))
- 4.包名可以使用“..”代表任意个数 execution(* *...类名称.方法名称(参数列表))
- 5.类名与方法名可以使用“*”代表任意 execution(* *...*.*(参数列表))
- 6.参数列表可以使用".."代表任意个数任意类型 execution(* *...*.*(..))
注:如果有参数 int======>int; String===>java.lang.String
xml版的面向切面编程案例部分代码展示
//日志工具类
public class Logger {
public void brforeLogger(){
System.out.println("日志类logger中调用前置Logger方法进行日志记录");
}
public void returnLogger(){
System.out.println("日志类logger中调用返回Logger方法进行日志记录");
}
public void throwLogger(){
System.out.println("日志类logger中调用异常Logger方法进行日志记录");
}
public void afterLogger(){
System.out.println("日志类logger中调用后置Logger方法进行日志记录");
}
//环绕通知
public Object arroundMethod(ProceedingJoinPoint pjp){
Object obj=null;
try{
System.out.println("环绕---------前置通知");
//切点方法
Object[] args = pjp.getArgs(); //参数
obj = pjp.proceed(args); //调用切点的所有方法
System.out.println("环绕---------返回通知");
}catch (Throwable e){
System.out.println("环绕---------异常通知");
}finally {
System.out.println("环绕---------后置通知");
return obj;
}
}
}
//applicationContext.xml
<!--注入业务层-->
<bean id="accountServiceImp" class="com.apesource.service.AccountServiceImp"></bean>
<!--注入日志记录层-->
<bean id="logger" class="com.apesource.util.Logger"></bean>
<!--配置AOP-->
<aop:config>
<!--配置切面-->
<aop:aspect id="aopAspect" ref="logger">
<!--配置通知类型,并建立通知方法和切入点方法的关联-->
<!--切点 expression = execution(修饰符{可省略} 返回值 包名称.类名称.方法名称(参数列表))-->
<aop:pointcut id="dian" expression="execution(* com.apesource.service.*.*(..))"/>
<!--通知-->
<!-- <aop:before method="brforeLogger" pointcut-ref="dian"></aop:before>-->
<!-- <aop:after-returning method="returnLogger" pointcut-ref="dian"/>-->
<!-- <aop:after-throwing method="throwLogger" pointcut-ref="dian"/>-->
<!-- <aop:after method="afterLogger" pointcut-ref="dian"/>-->
<aop:around method="arroundMethod" pointcut-ref="dian"/>
</aop:aspect>
</aop:config>
//测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test01 {
@Autowired
public IAccountService service;
@Test
public void show1(){
service.update();
System.out.println("----------");
service.save(1);
System.out.println("-----------");
service.delete();
}
}
注解版的面向切面编程案例部分代码展示
//logger日志
@Component
@Aspect //切面
public class Logger {
@Pointcut("execution(* com.apesource.service.*.*(..))")
public void dian(){
}
@Before("dian()")
public void beforeLogger(){
System.out.println("日志类logger中调用前置Logger方法进行日志记录");
}
@AfterReturning("dian()")
public void returnLogger(){
System.out.println("日志类logger中调用返回Logger方法进行日志记录");
}
@AfterThrowing("dian()")
public void throwLogger(){
System.out.println("日志类logger中调用异常Logger方法进行日志记录");
}
@After("dian()")
public void afterLogger(){
System.out.println("日志类logger中调用后置Logger方法进行日志记录");
}
//环绕通知
// @Around("dian()")
public Object arroundMethod(ProceedingJoinPoint pjp){
Object obj=null; //保存主业务犯法的返回值
try{
System.out.println("环绕---------前置通知");
//切点方法
Object[] args = pjp.getArgs(); //参数
obj = pjp.proceed(args); //调用切点的所有方法
System.out.println("环绕---------返回通知");
}catch (Throwable e){
System.out.println("环绕---------异常通知");
}finally {
System.out.println("环绕---------后置通知");
return obj;
}
}
}
//applicationContext.xml
<!--扫描-->
<context:component-scan base-package="com.apesource"></context:component-scan>
<!--开启spring注解的aop动态代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
标签:Java,void,System,class,AOP,println,设计模式,public,out
From: https://blog.csdn.net/weixin_64562166/article/details/141032450