Spring
小结Spring
github下载:https://github.com/spring-projects/spring-framework/releases
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)的框架!
第一个IOC程序
public class UserDaoImpl implements UserDao {
public void getUser() {
System.out.println("UserDaoImpl.......");
}
}
public class UserDaoOracleImpl implements UserDao{
public void getUser() {
System.out.println("UserDaoOracleImpl.......");
}
}
public class UserServiceImpl implements UserService{
// private UserDao userDao = new UserDaoImpl();
private UserDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="UserDaoImpl" class="com.kuang.dao.UserDaoImpl"/>
<bean id="UserDaoOracleImpl" class="com.kuang.dao.UserDaoOracleImpl"/>
<bean id="UserServiceImpl" class="com.kuang.service.UserServiceImpl">
<property name="userDao" ref="UserDaoOracleImpl"/>
</bean>
</beans>
public class TestIoc {
public static void main(String[] args) {
//获取ApplicationContext,拿到spring的容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
//容器在手,天下我有,需要什么就直接get什么
UserServiceImpl userServiceImpl = (UserServiceImpl)applicationContext.getBean("UserServiceImpl");
userServiceImpl.getUser();
}
}
IOC创建对象的方式
- 使用无参构造创建对象,默认
public class User {
private String name;
public User() {
System.out.println("wucan........");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.kuang.pojo.User">
<property name="name" value="kuangshen"/>
</bean>
</beans>
public class Test01 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
}
}
-
假设我们要使用有参构造创建对象。
- 下标赋值
- 通过类型创建(不推荐)如果两个相同的入参就不行
- 直接通过参数名来设置
public class User {
private String name;
public User(String name) {
this.name = name;
System.out.println("youcan........");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//方法一:下标赋值
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg index="0" value="qiangjiang"/>
</bean>
//方法二:类型赋值
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg type="java.lang.String" value="kaungshne"/>
</bean>
方法三:参数名赋值(推荐使用)
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg name="name" value="kuangshen3"/>
</bean>
public class Test01 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
}
}
总结:在配置文件加载的时候,容器中的对象就已经初始化了
别名
//两种方式
//
<bean id="user" class="com.kuang.pojo.User" name="u1,u2,u3,u4,u5">
<!--<constructor-arg index="0" value="qiangjiang"/>-->
<!--<constructor-arg type="java.lang.String" value="kaungshne"/>-->
<constructor-arg name="name" value="kuangshen3"/>
</bean>
<alias name="user" alias="u0"/>
Import
将不同的beans.xml合并到一个applicationContext.xml中,在applicationContext.xml中用import导入
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="beans.xml"/>
<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
</beans>
依赖注入
- 构造器注入
- Set方式注入【重点】
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
public class Address {
private String address;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.kuang.pojo.Address">
<property name="address" value="jiangsu"/>
</bean>
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="qingjang"/>
<property name="address" ref="address"/>
<property name="books">
<array>
<value>红楼梦</value>
<value>水浒传</value>
<value>西游记</value>
<value>三国演义</value>
</array>
</property>
<property name="hobbys">
<list>
<value>听歌</value>
<value>看电影</value>
<value>敲代码</value>
</list>
</property>
<property name="card">
<map>
<entry key="身份证" value="321088199292929292"/>
<entry key="电话" value="32108819929"/>
</map>
</property>
<property name="games">
<set>
<value>LOL</value>
<value>炉石</value>
<value>云顶之奕</value>
</set>
</property>
<property name="wife">
<null/>
</property>
<property name="info">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
public class TestDI {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Student student = (Student) context.getBean("student");
Student student2 = (Student) context.getBean("student");
System.out.println(student==student2);
}
}
bean的作用域
- 单例模式(spring的默认机制)
<bean id="student" class="com.kuang.pojo.Student" scope="singleton">
- 原型模式
<bean id="student" class="com.kuang.pojo.Student" scope="prototype">
- 其余的request、session、application这些只能在web开发中使用到!
Bean的自动装配
- 自动装配是Spring满足bean依赖一种方式!
- Spring会在上下文中自动寻找,并自动给bean装配属性!
在Spring中有三种装配的方式
- 在xml中显式地配置
- 在java中显式配置
- 隐式地自动装配【重点】
@Autowired
public class People {
private String name;
@Autowired
private Dog dog;
@Autowired
private Cat cat;
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="people" class="com.kuang.pojo.People"/>
</beans>
public class Test01 {
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = context.getBean("people", People.class);
people.getCat().shout();
people.getDog().shout();
}
}
-
@Autowired 直接在属性上使用即可!也可以在set方式上使用!使用Autowired 我们可以不用编写Set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字ByName!
-
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value="xxx")去配置@Autowired的使用,指定一个唯一的bean对象注入!
public class People {
private String name;
@Autowired
@Qualifier(value = "dog11")
private Dog dog;
@Autowired
@Qualifier(value = "cat11")
private Cat cat;
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean id="dog11" class="com.kuang.pojo.Dog"/>
<bean id="dog22" class="com.kuang.pojo.Dog"/>
<bean id="cat11" class="com.kuang.pojo.Cat"/>
<bean id="cat22" class="com.kuang.pojo.Cat"/>
<bean id="people" class="com.kuang.pojo.People"/>
</beans>
required = true(不写默认是true)
这个表示:注入bean的时候该bean必须存在,不然就会注入失败!
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.kuang.pojo.Dog' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
required = false
这个表示:注入bean的时候如果bean存在,就注入成功,如果没有就忽略跳过,启动不会报错!但是不能直接使用,因为doRequiredTest为NULL!
@Resource
<bean id="dog11" class="com.kuang.pojo.Dog"/>
<bean id="dog22" class="com.kuang.pojo.Dog"/>
<bean id="cat11" class="com.kuang.pojo.Cat"/>
<bean id="cat22" class="com.kuang.pojo.Cat"/>
<bean id="people" class="com.kuang.pojo.People"/>
public class People {
private String name;
@Resource
private Dog dog;
@Resource
private Cat cat;
public class Test01 {
@Test
public void test01(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
People people = context.getBean("people", People.class);
people.getCat().shout();
people.getDog().shout();
}
}
两个dog,cat的bean会报错
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.kuang.pojo.Dog' available: expected single matching bean but found 2: dog11,dog22
resource先根据id,再通过class,因为这里ByName匹配不到,class又有两个,所以报错
解决:通过@Resource(name = "")指定
public class People {
private String name;
/*@Autowired
@Qualifier(value = "dog11")*/
@Resource(name = "dog11")
private Dog dog;
/*@Autowired
@Qualifier(value = "cat11")*/
@Resource(name = "cat11")
private Cat cat;
小结:
@Autowired和@Resource的区别:
-
都是用来自动装配的,都可以放在属性字段上
-
@Autowired 通过ByName的方式实现,而且必须要求这个对象存在(除非构造方法有@Nullable)
public People(@Nullable String name) { this.name = name; } -
@Resource 通过ByType的方式实现,如果找不到名字,则通过ByType实现!如果两个都找不到就报错
@Component
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao 【@Repository】
- service 【@Service】
- controller 【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
注意的问题:想让注解生效,就必须开启注解的支持
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.kuang"/>
<context:annotation-config/>
拦截器
- 新建一个Moudule , springmvc-07-Interceptor , 添加web支持
- 配置web.xml 和 springmvc-servlet.xml 文件,添加jar包
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描指定的包,下面所有注解类交给IOC容器管理-->
<context:component-scan base-package="com.kuang.controller"/>
<!--静态资源过滤-->
<mvc:default-servlet-handler/>
<!--JSON乱码问题配置-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
编写一个拦截器
public class MyInterceptor implements HandlerInterceptor {
//在请求处理的方法之前执行
//如果返回true执行下一个拦截器
//如果返回false就不执行下一个拦截器
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("------------处理前------------");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("------------处理后------------");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("------------清理------------");
}
}
在applicationContext.xml的配置文件中配置拦截器
<!--关于拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<!--bean配置的就是拦截器-->
<bean class="com.kuang.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
编写控制器
@Controller
public class InterceptorController {
@RequestMapping("/interceptor")
@ResponseBody
public String testFunction() {
System.out.println("控制器中的方法执行了");
return "hello";
}
}
前端 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/interceptor">拦截器测试</a>
</body>
</html>
ok
浙公网安备 33010602011771号