栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring(eclipse)简要笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring(eclipse)简要笔记

目录

1.spring核心容器

1.2 ApplicationContext

 1.2.2 通过FileSystemXmlApplicationContext创建

2.XML的配置信息

3.spring的依赖注入(DI)

4.代理

5.AOP


1.spring核心容器

1.1 BeanFactory

其主要是一个管理Bean的工厂,主要负责初始化各种Bean,并调用他们的生命周期方法,语法如下:

//1.加载bean工厂
 BeanFactory beanfactory=new ClassPathXmlApplicationContext("app*.xml");

1.2 ApplicationContext

ApplicationContext是BeanFactory的子接口,也被称为应用上下文,是另一种常用的Spring的核心容器。它不仅包含了BeanFactory的所有功能,还添加了对国际化、资源访问、事件传播等方面的支持。语法如下:

1.2.1 通过ClassPathXmlApplicationContext创建(常用)

//1.加载bean工厂
 ApplicationContext applicationcontext=new ClassPathXmlApplicationContext("app1.xml");

 1.2.2 通过FileSystemXmlApplicationContext创建

FileSystemXmlApplicationContext会从指定的文件系统路径(绝对路径)区寻找指定的XML配置文件,找到并装载完成ApplicationContext的实列化工作,其灵活性较差,语法如下:

//1.加载bean工厂
 ApplicationContext applicationcontext=new FileSystemXmlApplicationContext(String configLocation);

2.XML的配置信息

以下示例显示了基于 XML 的配置元数据的基本结构:

 
 
 ​
       (1) (2)
         
     
         
     
         
     
 ​
 
  • (1) id属性是标识单个 bean 定义的字符串。

  • (2) class属性定义 bean 的类型并使用完全限定的类名。

id属性的值是指协作对象。在此示例中未显示用于引用协作对象的 XML。

3.spring的依赖注入(DI)

1.依赖注入:

IOC的作用:降低程序之间的耦合(依赖关系)

概念:依赖关系的管理交给spring维护,在当前类需要用到其他类的对象,由spring为我们提供,只需在配置文件中说明关系的维护;

2.能够注入的数据有三类:

1) 基本类型和string

2) 其他bean类型(在配置文件中或者注解配置过的bean)

3)复杂集合类型

3.两种注入方式

1)使用构造函数

1.先建立一个user类

public class user {
     private String username;
     private int password;
     private List list;
     
     public user(String username, int password, List list) {
         super();
         this.username = username;
         this.password = password;
         this.list = list;
     }
 @Override
     public String toString() {
         return "user [username=" + username + ", password=" + password + ", list=" + list + "]";
     }
 }

2.配置xml文件

 

 
     
 
 
 
 
 
 "constructorvalue1"
 "constructorvalue2"
 
 
 
 

3.运行输出

 @Test
     public void testem() {
         //1.加载bean工厂
         ApplicationContext beanfactory=new ClassPathXmlApplicationContext("app5.xml");
         //2.获取bean
         user u1=(user) beanfactory.getBean("user1");
         System.out.println(u1);
     }

2)set方法注入(常用)

设值注入是IoC容器使用成员变量的setter方法来注入被依赖对象。需满足两点:

(1)Bean类必须提供一个默认的无参构造方法。

(2)Bean类必须为需要注入的属性提供对应的setter方法。

1.先建一个user类

 
package com.ds.spring;
 ​
 import java.util.List;
 ​
 public class user {
     private String username;
     private int password;
     private List list;
         
     public user() {
         super();
         // TODO Auto-generated constructor stub
     }
     public String getUsername() {
         return username;
     }
     public void setUsername(String username) {
         this.username = username;
     }
     public int getPassword() {
         return password;
     }
     public void setPassword(int password) {
         this.password = password;
     }
     public List getList() {
         return list;
     }
     public void setList(List list) {
         this.list = list;
     }
     @Override
     public String toString() {
         return "user [username=" + username + ", password=" + password + ", list=" + list + "]";
     }
 }
 ​

2.进行xml文件配置

 
 
 
 
 
 
 
 
 "setlistvalue1"
 "setlistvalue2"
 
 
 
 

3.运行

 
public class test {
         @Test
     public void teste() {
         //1.加载bean工厂
         ApplicationContext beanfactory=new ClassPathXmlApplicationContext("app5.xml");
         //2.获取bean
         user u2=(user)beanfactory.getBean("user2");
         System.out.println(u2);
     }
     }

4.基于Annotation的装配

1)Spring中常用注解如下

  • @Commponent相当于new了个对象,也就是相当于中id的值,(不写括号里的名字的话默认类名的小写)

  • @Repository功能与Commponent相同,但是其常用于数据访问层(DAO层)

  • @Service功能与Commponent相同,其常用于业务层(Service层)

  • @Controller功能与Commponent相同,其常用于控制层

  • @Autowired,该注解默认使用按类型自动装配Bean的方式。 使用该注解完成属性注入时,类中无需setter。当然,若属性有setter,则也可将其加到setter上。

  • @Qualifier的value属性用于指定要匹配的Bean的id值。同样类中无需setter,也可加到setter上。@Autowired与@Qualifier相当于@Resource(name=" ")

  • @Scope,其value属性用于指定作用域。默认为singleton

  • @Value,该注解的value属性用于指定要注入的值。

  • @Resource是java自带的注解

@Resource注解既可以按名称匹配Bean,也可以按类型匹配Bean。使用该注解,要求JDK必须是6及以上版本。 (1)按类型注入域属性 @Resource注解若不带任何参数,看 Spring 容器中的 bean 中的 id 与@ Resource 要注解的那个变量属性名是否相 同,如相同,匹配成功;如不同 看 spring 容器中 bean 的 id 对应的类型是否与@ Resource 要注解的那个变量属性对应的类型是否相等,若相等,匹配成功,若不相等,匹配失败。

(先比较名字cat1和cat发现不同,然后就比较类名Cat和Cat发现相同,匹配成功)

2)按名称注入域属性 @Resource注解指定其name属性,则name的值即为按照名称进行匹配的Bean的id。

如下一个例子:

1.建立一个Cat类

package com.hkd.zhujie;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("cat1")//指定id为cat1
public class Cat {
	@Value("波斯猫")
	String name;
	public void shoutc() {
		System.out.println(name+"喵喵喵!");
	}
}

2.建立一个Dog类

package com.hkd.zhujie;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component//默认id为dog
public class Dog {
	@Value("金毛")
	String name;
public void shoutd() {
	System.out.println(name+"汪汪汪!");
}
}

3.建立Animal类,并引入Cat和Dog‘类

package com.hkd.zhujie;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Animal {
	//@Autowired//默认按类名进行找
	@Resource//默认先根据id和名字找,再根据类名找
	Dog dog;
//	@Autowired
//	@Qualifier("cat1")//按id名进行找
	@Resource(name="dog")//按id名找
	Cat cat;
	public Dog getDog() {
		return dog;
	}
	public void setDog(Dog dog) {
		this.dog = dog;
	}
	public Cat getCat() {
		return cat;
	}
	public void setCat(Cat cat) {
		this.cat = cat;
	}
	public void shouta() {
		dog.shoutd();
		cat.shoutc();
	}
	

}

4.扫描包(app6.xml)




	                    
	                    
	                    

5.测试

package com.hkd.zhujie;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {
public static void main(String[] args) {
	ApplicationContext app=new ClassPathXmlApplicationContext("app6.xml");
	Animal a=(Animal)app.getBean("animal");
	a.shouta();
}
}

5.使用JavaConfig配置

1)其完全不使用Spring的XML进行配置,全部交给Java来做,JavaConfig是Spring的一个子项目,在Spring4后,它成了一个核心功能。

1.建一个user类

package com.ds.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
public class user {
@Value("李白")
String name;

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

@Override
public String toString() {
	return "user [name=" + name + "]";
}

}

2.再建一个config类来配置

package com.ds.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration//代表的是一个配置类,相当于XML文件
public class config {
@Bean//这个方法的名字,相当于bean标签中的id属性
//返回值相当于bean标签的class属性
public user getuser() {
	return new user();
}
}

3.运行

package com.ds.config;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class test {
public static void main(String[] args) {
ApplicationContext app=new AnnotationConfigApplicationContext(config.class);
user u=(user)app.getBean("getuser");//方法名
System.out.println(u.getName());
}
}

4.代理

1)其含义就是通过第三方来代理我们的工作,用如下例子来说明

1.先写一个接口userservice

package com.fbw.agent;

public interface userservice {
	void add();
	void delete();
	void update();
	void quary();

}

2.userserviceimp实现这个接口

package com.fbw.agent;


//不能改源代码,创一个代理类
public class userserviceimp implements userservice {

	public void add() {
		// TODO Auto-generated method stub
        //System.out.println("使用了add方法");一般会这样写,但这样会比较臃肿,而且修改了源码,为了避免这些所以引出了代理
System.out.println("add a user");
	}

	public void delete() {
		// TODO Auto-generated method stub
        //System.out.println("使用了delete方法");
System.out.println("delete a user");
	}

	public void update() {
		// TODO Auto-generated method stub
        //System.out.println("使用了update方法");
System.out.println("update a user");
	}

	public void quary() {
		// TODO Auto-generated method stub
        //System.out.println("使用了quary方法");
System.out.println("quary a user");
	}

}

正常的话直接new对象就可以调用方法了,但现在有一个在每个方法上都加上“使用了...方法“的输出,而且是在不改变源码(修改源码是大忌)的条件下的需求,此时就要引入代理,代理可分为静态代理和动态代理:

1)静态代理

3.接上面的例子,创建一个名为userserviceagent的代理类来处理需求

package com.fbw.agent;


//代理类
public class userserviceagent implements userservice {
	userserviceimp usp;
	public void setUsp(userserviceimp usp) {
		this.usp = usp;
	}
    
    //引入需求
	public void log(String msg) {
	System.out.println("使用了"+msg+"方法");
}
	@Override
	public void add() {
		// TODO Auto-generated method stub
		log("add");
		usp.add();
	}

	@Override
	public void delete() {
		// TODO Auto-generated method stub
log("delete");
usp.delete();
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
log("update");
usp.update();
	}

	@Override
	public void quary() {
		// TODO Auto-generated method stub
		log("quary");
		usp.quary();

	}

}

此时加入的需求就直接引用到了代理类里,源码也不必修改

4.测试

package com.fbw.agent;

public class test {
	public static void main(String[] args) {
		//要代理的类,真实角色
		userserviceimp usi=new userserviceimp();
		//代理类
		userserviceagent usa=new userserviceagent();
		//设置要代理的类
		usa.setUsp(usi);
		//调用方法
		usa.add();
		
	}
}

2)动态代理

有静态代理可以看出,其虽然实现了需求,但是其比较繁琐每次需要完成需求都要建立一个代理类,所以就引入了动态代理,动态代理是在反射的基础上完成的。

3.接上面的例子我们可以创建一个动态的代理万能类其需要实现InvocationHandler接口,如下(类名为ProxyInvocationHandler)

package com.fbw.agent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import jdk.nashorn.internal.runtime.linker.InvokeByName;


//动态的工具类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
	//被代理的接口
private Object target;


public void setTarget(Object target) {
	this.target = target;
}

//生成得到代理类
public Object getproxy() {
		
	return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(), this);
}
	
	
	//处理代理实例,并返回结果
	@Override
	public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
		// TODO Auto-generated method stub
		
		//通过arg1.getName()来获取调用的方法名
		log(arg1.getName());
		Object result=arg1.invoke(target, arg2);
		return result;
	}
	public void log(String msg) {
		System.out.println("执行了"+msg+"方法");
	}

}
  • target:代表的是要被代理的接口

  • setTarget(Object target):为了使将要生成的代理类也实现接口

  • getproxy():其return的是要代理的类,其目的是为了的得到要代理的类,即userserviceimp类

  • newProxyInstance(参数1,参数2,参数3):其三个参数分别代表:

    • 用哪个类加载器去加载代理对象,即ProxyInvocationHandler类

    • 动态代理的类需要实现的接口,即service接口

    • 动态代理方法在执行时,会调用h里面的invoke方法去执行(在这个例子里就是this,实际上是ProxyInvocationHandler类中的invoke()方法)

  • this:代表的就是本类

  • getClass():返回值是类

  • getClassLoader():返回类的加载器

  • getInterfaces():返回类的接口

  • invoke(Object arg0, Method arg1, Object[] arg2):

    • arg0:就是代理对象,也就是target

    • arg1:调用的方法

    • arg3:方法中的参数

  • arg1.invoke(Object obj,Object args[])的作用就是调用arg1类代表的方法,其中obj是接口名,args调用的obj中的方法的,也就是说其返回的是obj接口中的args方法(用了反射,就是Method arg1.invoke())。就是使代理类在拥有userserviceimp中的所有方法的同时也能增加方法。

  • arg1.getName():调用方法的名字

    4.测试

    package com.fbw.agent;
    
    public class test1 {
    	public static void main(String[] args) {
    		//真实角色
    		userserviceimp u=new userserviceimp();
    		//生成代理类的工具,代理角色现在不存在
    		ProxyInvocationHandler pih=new ProxyInvocationHandler();
    		//真实角色已经实现了接口,代理角色也要实现接口,使将要生成的代理类也实现接口,现在其也代理了这个接口,并有了真实角色的方法
    		pih.setTarget(u);
    		//用接口强转,动态生成代理类,接口是连接真实角色和代理工具的桥梁
    		userservice p=(userservice) pih.getproxy();
    		p.add();
    	}
    
    }

流程:先new真实角色和代理工具,然后调用代理工具中的setTaget(u)方法把实现userservice接口的类的对象传入(使代理对象实现接口),代理类对象的getproxy()方法会返回生成代理对象,而这个代理对象在生成时会调用invoke()方法,这个invoke()方法会使代理类对象拥有userserviceimp中的所有方法,也能使其拥有userserviceimp,中没有的方法如本例的log()方法。

5.AOP

aop是面向切面的编程,其实它和代理很像,都是要过第三方类在不改变源代码的情况下完成需求。

目前流行的是Spring AOP和AspectJ,Spring AOP使用的是纯java实现,不需要专门的编译过程和类的加载器,在运行期间通过代理方式向目标类织入增强代码。

AspectJ是基于java语言的AOP框架,AspectJ扩展了java语言,提供了专门的编译器,并在编译时提供了横向代码的织入。

spring有五种通知方法:

  • Around 环绕通知 org.aopalliance.intercept.MethodInterceptor 拦截对目标方法调用,可用于日志、事务管理等功能

  • Before 前置通知 org.springframework.aop.MethodBeforeAdvice 在目标方法调用前调用,可用于权限管理等功能

  • After 后置通知 org.springframework.aop.AfterReturningAdvice 在目标方法调用后调用,可用于关闭流,上传文件,删除临时文件等功能

  • Throws 异常通知 org.springframework.aop.ThrowsAdvice 当目标方法抛出异常时调用,可以应用于处理异常记录日志等功能

  • 引介通知 org.springframework.aop.IntroductionInterceptor 在目标类中添加一些新的方法和属性,可以应用于修改老版本程序

    以下例子都是围绕这五个通知来进行

1.使用Spring的API接口

1)首先先建立userservice接口

package com.fbw.aop;

public interface userservice {
	void add();
	void delete();
	void update();
	void quary();
}

2)建立serviceimp类来实现接口

package com.fbw.aop;

public class userserviceimp implements userservice {

	public void add() {
		// TODO Auto-generated method stub
System.out.println("add a user");
	}

	public void delete() {
		// TODO Auto-generated method stub
System.out.println("delete a user");
	}

	public void update() {
		// TODO Auto-generated method stub
System.out.println("update a user");
	}

	public void quary() {
		// TODO Auto-generated method stub
System.out.println("quary a user");
	}

}

3)建立两个类(类都要继承通知类)来验证(本例子用的是前置通知和后置通知):

package com.fbw.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class log implements MethodBeforeAdvice {
	//arg0:要执行的目标对象的方法
	//arg1:参数
	//arg2:目标对象
	@Override
	public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
		// TODO Auto-generated method stub
        //输出哪个包下的方法被执行
		System.out.println(arg2.getClass().getName()+"的"+arg0.getName()+"被执行了");
	}

}


package com.fbw.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class afterlog implements AfterReturningAdvice {

	//arg0:返回值
	@Override
	public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        //输出执行的方法和返回值
		System.out.println(arg1.getName()+"方法被执行了,返回结果为:"+arg0);
	}

}

4)配置xml文件



	                    
	                    
	                    
	       
			
			
			
				
			
			
			 
			
			
			
			
			
			

5)测试

package com.fbw.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {
	public static void main(String[] args) {
		ApplicationContext app=new ClassPathXmlApplicationContext("aop.xml");
		userservice u=(userservice)app.getBean("ui");
		u.add();
	}

}

2.使用自定义类

1)JoinPoint 对象

JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象. 常用api:

方法名功能
Signature getSignature();获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
Object[] getArgs();获取传入目标方法的参数对象
Object getTarget();获取被代理的对象
Object getThis();获取代理对象

2)ProceedingJoinPoint对象

ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中, 其中添加了 Object proceed() throws Throwable //执行目标方法 Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法 两个方法.

1)定义一个div类用来构造5种通知的方法

package com.fbw.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class div {
	//前置通知
void before(JoinPoint joinpoint) {
	System.out.println("前置通知:模拟执行权限检查。。。。");
	System.out.println("目标类是:"+joinpoint.getTarget());
	System.out.println("被植入增强处理的目标方法是:"+joinpoint.getSignature().getName());
	
}
//后置通知
void after(JoinPoint joinpoint) {
	System.out.println("后置通知:模拟记录日志。。。。");
	System.out.println("被植入增强处理的目标方法为:"+joinpoint.getSignature().getName());
}

//环绕通知
	
Object round(ProceedingJoinPoint proceedingjoinpoint) throws Throwable {
	System.out.println("环绕开始:执行目标之前,模拟开启事务");
	//执行当前目标方法
	Object obj=proceedingjoinpoint.proceed();
	System.out.println("环绕结束:执行目标方法之后,模拟关闭事务");
	return obj;
}
//异常通知
void yc(JoinPoint joinpoint,Throwable e) {
	System.out.println("出现了异常,异常信息是:"+e.getMessage());
}

//最终通知
void fianlnotice() {
	System.out.println("通知:结束了!!!");
}
}

2)设置xml文件



	                    
	                    
	                    
	       
			
			
			
			
			
			
			
		
			
			
			
			
			
			
			

3)测试

package com.fbw.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {
	public static void main(String[] args) {
		ApplicationContext app=new ClassPathXmlApplicationContext("aop.xml");
		userservice u=(userservice)app.getBean("ui");
		u.add();
	}

}

3.使用注解

1)创建一个使用注解的类

package com.fbw.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class a {
	@Pointcut("execution(* com.fbw.aop.userserviceimp.*(..))")//相当于切入点,需要一个空的方法
	public void my() {
		
	}
	@Before("my()")
		//前置通知
	void before(JoinPoint joinpoint) {
		System.out.println("前置通知:模拟执行权限检查。。。。");
		System.out.println("目标类是:"+joinpoint.getTarget());
		System.out.println("被植入增强处理的目标方法是:"+joinpoint.getSignature().getName());
		
	}
	@AfterReturning("my()")
	//后置通知
	void after(JoinPoint joinpoint) {
		System.out.println("后置通知:模拟记录日志。。。。");
		System.out.println("被植入增强处理的目标方法为:"+joinpoint.getSignature().getName());
	}

	//环绕通知
		
	@Around("my()")
	Object round(ProceedingJoinPoint proceedingjoinpoint) throws Throwable {
		System.out.println("环绕开始:执行目标之前,模拟开启事务");
		//执行当前目标方法
		Object obj=proceedingjoinpoint.proceed();
		System.out.println("环绕结束:执行目标方法之后,模拟关闭事务");
		return obj;
	}
	@AfterThrowing(value = "my()",throwing = "e")
	//异常通知
	void yc(JoinPoint joinpoint,Throwable e) {
		System.out.println("出现了异常,异常信息是:"+e.getMessage());
	}

	//最终通知
	@After("my()")
	void fianlnotice() {
		System.out.println("通知:结束了!!!");
	}
	}

2)配置xml文件



	                    
	                    
	                    
	                    
	                    

3)测试运行

package com.fbw.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {
	public static void main(String[] args) {
		
		ApplicationContext app=new ClassPathXmlApplicationContext("a.xml");
		userservice u=(userservice)app.getBean("ui");
		u.add();
	}

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/571740.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号