spring
springMaven依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.7</version> </dependency>
IOC
IOC控制反转,是一种设计思想,DI依赖注入是IOC思想的一种实现方式
在我们写程序时对象的创建与对象间的依赖全是程序的硬编码实现的,ioc的思想就是将程序的创建与依赖交给第三方管理,我们只需要从第三方哪里去取我们想要的即可,而不用关心对象的创建与依赖关系
IOC容器
IOC的第三方容器,我们可以从里面去取我们想要的类
Bean
可以理解为IOC容器里装的是bean
helloSpring
类User
public class User { String str; public void helloSpring(){ System.out.println(str+" hello spring"); } public void setStr(String str) { this.str = str; } }
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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <!--将该类交给容器托管--> <bean id="user" class="com.qiu.pojo.User" > <property name="name" value="qlh"/> </bean> </beans>
测试类
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //得到spring上下文(核心)context,从里面提取bean ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = context.getBean("user", User.class); user.helloSpring(); } }
输出内容
qlh hello spring
可以看见上述测试代码,user类是从context里取的而不是我们new出来的
启动注解支持
想要使用spring注解则必须启动注解支持, 和有spring-aop的包
配置注解支持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:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置扫描包的路径,使用注解的类必须在该包下面,否则注解无效--> <context:component-scan base-package="com.qiu.pojo" /> <!-- 启动注解支持 --> <context:annotation-config/> </beans>
bean的注册
可以理解为将bean加入容器
xml
<!--添加bean--> <bean id="user" class="com.qiu.pojo.User">
@Component
在实体类上加入@Component
@Component public class User { }
依赖注入
xml配置文件
xml方式的依赖注入是依靠set方法注入的,通过该方式注入的属性必须有set方法
<bean id="user" class="com.qiu.pojo.User" scope="prototype"> <!--属性赋值 name = str为属性名,而且该属性必须有set方法,value--> <property name="str" value="qlh"/> <!--实体类可用ref引入其它bean的,ref写引入其它bean的id--> <property name="" ref="benId"/> </bean>
public class MessageBean { private String username; //用户名 private String fileDir; //上传路径 private Set<String> types;//允许上传类型 private List<String> hbms; private Set<String> city; private Map<String, String> books; private Properties props; //注入一个字符串,分析之后给其赋值 public void setTypes(String str){ String[] arr = str.split(","); types = new HashSet<String>(); for (String string : arr) { types.add(string); } } public void setUsername(String username) { this.username = username; } public void setFileDir(String fileDir) { this.fileDir = fileDir; } public void setCity(Set<String> city) { this.city = city; } public void setHbms(List<String> hbms) { this.hbms = hbms; } public void setBooks(Map<String, String> books) { this.books = books; } public void setProps(Properties props) { this.props = props; } public void show(){ System.out.println("用户名:" + username); System.out.println("上传路径" + fileDir); System.out.println("--hbm文件如下--"); for (String string : hbms) { System.out.println(string); } System.out.println("--city如下--"); for (String string : city) { System.out.println(string); } System.out.println("--图书信息显示--"); Set set = books.keySet(); for (Object object : set) { System.out.println(object+" "+books.get(object)); } System.out.println("--props参数如下--"); Set<String> key = props.stringPropertyNames(); Iterator<String> iterator = key.iterator(); while(iterator.hasNext()){ String string = (String) iterator.next(); System.out.println(string+" "+props.getProperty(string)); } System.out.println("--允许上传文件类型--"); for (String string : types) { System.out.println(string); } } }
<!-- 各种数据类型的注入 --> <bean id="messageBean" class="com.henu.spring.MessageBean"> <!-- 字符串 --> <property name="username" value="root"/> <property name="fileDir" value="D:\\images"></property> <property name="types" value="jdp,gif,ipeg"></property> <!-- 列表 --> <property name="hbms"> <list> <value>lengzuai nei hou !</value> <value>lengnei nei hou !</value> </list> </property> <property name="city"> <set> <value>郑州</value> <value>开封</value> </set> </property> <!-- Map --> <property name="books"> <map> <entry key="1" value="红楼梦"></entry> <entry key="2" value="三国演义"></entry> <entry key="3" value="西游记"></entry> <entry key="4" value="水浒传"></entry> </map> <!-- Properties --> </property> <property name="props"> <props> <prop key="hibernate.show_sql"> <!-- value --> true </prop> <prop key="hibernate.format_sql"> true </prop> <prop key="hibernate.hibernate_sql"> true </prop> </props> </property> </bean> </beans>
注解(value)
对于一些基本类型可使用类型可使用@Value注解注入值
public class User { @Value("ss") String str; public void setStr(String str) { this.str = str; } }
等价
<bean id="user" class="com.qiu.pojo.User" autowire="byName"> <property name="str" value="ss"/> </bean>
自动装配(autowire)
自动装配的意思是假如bean的属性也被spring 容器托管了,可不用配置依赖注入,直接自动装配即可
常用的装配方式有byName(根据bean的id名等于属性名则匹配),byType(属性的类型等于bean的类型)
配置文件方式
bean标签autowire属性可设置自动装配
<!-- 可设置为byType --> <bean id="user" class="com.qiu.pojo.User" autowire="byName"/>
注解方式
这种方式可省略set方法
@Autowired
默认byType机制
类属性字段加Autowired,默认是bytype方式
@Autowired //默认是bytype User user; //可与@Qualifier("id名") 搭配使用 @Autowired @Qualifier("id名") //可指定装配指定id的bean User user;
@Resource
功能相对于autowired更强大一点
@Resource //先byName找不到,则byType,两个都找不到则报错 User user; @Resource("id名") //可指定装配指定id的bean User user;
作用域 (单例模式、原型模式)
单例模式:每次注入的是同一个实例
原型模式:每次注入的是不同的实例
bean标签的scope参数可配置
spring 默认单例模式 singleton
<!--单例模式 spring默认是单例模式,可不写--> <bean id="user" class="com.qiu.pojo.User" scope="singleton"> <!--属性赋值 str为属性名,而且该属性必须有set方法--> <property name="str" value="qlh"/> </bean> <!--原型模式--> <bean id="user" class="com.qiu.pojo.User" scope="prototype"> <property name="str" value="qlh"/> </bean>
AOP(面向切面编程)
当我们对某个类功能增强时:添加新功能
比如加入日志功能时,我们虽然可以直接去修改原来那个类加入日志,但是这不否和面向对象7大原则最终要的一条开闭原则,在添加功能时直接改原代码是大忌,如果项目小还好,项目大的话假如入代码改崩了会造成不可预料的后果。
代理模式
代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
比如房东出租房子,房东可以将出租房子这件事交给中介来做,而想要租房子的人直接找中介即可
代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
因此我们可以通过代理模式来实现做到在不修改原类时,通过扩展一个代理类,给代理类添加新功能,从而实现功能增强
SpringAop
相关概念(了解即可)
-
Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
-
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
-
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
-
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
-
Target(目标对象):织入 Advice 的目标对象.。
-
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
maven依赖
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
注解方式
<?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:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" 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.2.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 配置扫描包的路径--> <context:component-scan base-package="com.qiu.pojo" /> <!-- 启动注解支持 --> <context:annotation-config/> <!-- 启动 @Aspect等注解的支持--> <aop:aspectj-autoproxy/> </beans>
public interface UserService { public void get(); public void add(); public void update(); public void delete(); } @Component public class UserServiceImpl implements UserService{ public void get(){ System.out.println("get"); } public void add(){ System.out.println("add"); } public void update(){ System.out.println("update"); } public void delete(){ System.out.println("delete"); } }
@Aspect //标注切面
@Component //注意别漏掉了该注解,切面也需要加入容器
public class AnnotationPointCut {
@Before("execution(* com.qiu.pojo.UserServiceImpl.*(..))")
public void before(){
System.out.println("方法执行前");
}
@After("execution(* com.qiu.pojo.UserServiceImpl.*(..))")
public void after(){
System.out.println("方法执行前");
}
@Around("execution(* com.qiu.pojo.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp){
System.out.println("环绕前");
try {
jp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("环绕后");
}
}
public class Test { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userServiceImpl", UserService.class); userService.add(); } }
执行结果
环绕前 方法执行前 add 方法执行前 环绕后
config(完全不使用xml文件)
我们可以用使用配置类代替xml文件两者可以等价
@Configuration //标注该类为spring配置类 @ComponentScan("com.qiu.pojo") //等价<context:component-scan base-package="com.qiu.pojo" /> public class SpringConfig { //注册一个bean //getUser 为id名 //等价<bean id="getUser" class="com.qiu.pojo.User"/> @Bean public User getUser(){ return new User(); } }
@Component public class User { @Value("小明") String str; public void helloSpring(){ System.out.println(str+" hello spring"); } public void setStr(String str) { this.str = str; } }
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); User user = context.getBean("getUser", User.class); user.helloSpring(); } }
浙公网安备 33010602011771号