applicationContext基础配置
IOC配置
1、 基本配置
<?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
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
</beans>
2、 给bean起别名
<!-- name属性用来给bean命名,原来名和name里的值都可以使用,并且可以用"," ";" " "分割 -->
<bean id="helloT" class="com.tcc.entity.HelloT" name="hello2,h1;h2 h3">
<!-- <constructor-arg name="stringT" value="3.1415926" /> -->
<property name="stringT" value="stringT"/>
</bean>
<alias name="" alias=""/>
3、 导入其他xml文件
<!-- 多个人开发时,用于引入别人写的xml配置文件 -->
<import resource="beans.xml"/>把类放入bean里
4、 把类放入bean里
<bean id="..." class="com.xxx.xxx"></bean>
5、 bean标签中属性
-
autowire自动注入:autowire=“byName|byType|no”
模式 说明 no 不使用自动装配。必须通过ref元素指定依赖,这是默认设置。由于显式指定协作者可以使配置更灵活、更清晰,因此对于较大的部署配置,推荐采用该设置。 byName 根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配 byType 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用byType方式进行自动装配。若没有找到相匹配的bean,则属性不会被设置。 -
scope Bean作用域:scope=“singleton|prototype|request|session|application|websocket”
-
name命名:name=“h1,h2;h3 h4”
- name属性用来给bean命名,原来名和name里的值都可以使用,并且可以用 " , or ; or 空格 "分割
<bean id="hello" class="com.tcc.entity.Hello" name="h1,h2;h3 h4"/>
6、实体类注入值(set注入,构造器注入)
6.1、set注入值(实体类中要有:set方法)
- set注入用:
<property name="string1" value="String1"/>
6.2、构造器注入值三种方法(实体类中要有:有参构造方法)
-
通过下标注入:
<!-- 通过下标赋值 --> <constructor-arg index="0" value="123456" />
-
通过类型注入: 如果属性类型相同则不能使用 不建议
<!-- 通过类型赋值,如果属性类型相同则不能使用 不建议 --> <constructor-arg type="java.lang.String" value="123456" />
-
通过变量名注入:
<!-- 通过变量名注入,最常用 --> <constructor-arg name="string1" value="3.1415" />
7、特殊类型注入值
-
引用类型注入:
<bean id="dog" class="com.tcc.entity.Dog"/> <bean id="cat" class="com.tcc.entity.Cat"/> <bean id="people" class="com.tcc.entity.People"> <property name="dog" ref="dog"/> <property name="cat" ref="cat"/> </bean>
-
数组:
<property name="shuZu1"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property>
-
集合:
<property name="list1"> <array> <value>2</value> <value>3</value> <value>4</value> </array> </property>
-
Map:
<property name="map1"> <map> <entry key="姓名" value="小黑"/> <entry key="爱好" value="女"/> </map> </property>
-
Set:
<property name="set1"> <set> <value>set1</value> </set> </property>
-
Null:
<property name="stringNull"> <null/> </property>
-
Properties:
<property name="properties1"> <props> <prop key="driver">com.mysql.jdbc.Driver</prop> <prop key="url">123123</prop> <prop key="username">root</prop> <prop key="password">admin</prop> </props> </property>
8、P命名空间
-
P命名空间(set注入):在bean标签里面加上 p:string1=“string1”
-
xml里面添加配置:xmlns:p=“http://www.springframework.org/schema/p”
<bean id="address" class="com.tcc.entity.Address" p:address="address1"/>
9、C命名空间
-
C命名空间(构造器注入):在bean标签里面加上 c:string1=“string1”
-
注意!:c是通过构造器注入的,所以该对象的所有属性要一次性都用C命名赋值以后才能构造成功否则有参构造将会缺少其他参数报错!
-
xml里面添加配置:xmlns:c=“http://www.springframework.org/schema/c”
<bean id="address" class="com.tcc.entity.Address" c:address="address1"/>
注解
-
环境配置
-
先导入spring-aop-4.3.7.RELEASE.jar包
<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:component-scan base-package="com.tcc.entity"/> <context:annotation-config/> </beans>
-
常用注解
1、@Autowired:用于属性的自动注入。
-
是【autowire=“byName”】和【autowire=“byType”】的结合体
-
他会先根据"byType"进行查询,如果没有匹配成功则通过"byName"查询。
-
@Autowired既可放在字段前,也可放在setter方法前
private String name; @Autowired private Dog dog; @Autowired private Cat cat;
-
2、 @Qualifier(value=“dog1”):和@Autowired一起使用。
-
如果byName和byType都不匹配,则通过value的值来寻找id匹配的值。
private String name; @Autowired @Qualifier("dog1") private Dog dog; @Autowired private Cat cat;
总结:使用 @Autowired注解自动装配依赖的过程如下: 1.首先根据属性的类型(或方法、构造方法参数的类型)在Spring 应用容器中查找类型匹配的bean 2.如果没有类型匹配的bean,抛出BeanCreationException;如果只有一个,则注入依赖,完成自动装 配;如果不只一个,则继续执行步骤3; 3.如果通过 @Qualifier指定了bean 名称,则从所有符合类型的bean中返回指定的bean,完成自动装 配;如果没有通过 @Qualifier制定bean 名称,则通过反射技术获取当前属性的名称作为bean 名称 返回指定的bean,完成自动装配。
3、 @Resource:@Resource由J2EE提供,作用相当于@Autowired。
-
@Autowired是按byType自动注入,而@Resource默认按 byName自动注入。
-
@Resource有两个属性是比较重要的,分别是name和type
-
@Resource既可放在字段前,也可放在setter方法前
private String name; /*@Autowired @Qualifier("dog1")*/ @Resource(name="dog") private Dog dog; /*@Autowired*/ @Resource(type=Cat.class) private Cat cat;
4、@Component:将类放入bean中
-
bean名称默认为将第一个字母转换为小写的类名。
-
bean名称默认为将第一个字母转换为小写的类名。
-
@Component注解唯一的一个可选参数是value,用于指定bean的名称(即id值,所以必须是唯一的)
@Component(value="computer") public class Computer { … } //注解中的value属性可以省略,可以简写为: @Component("computer") public class Computer { … }
Spring还提供了更加细化的用于定义bean的注解形式: 1.@Repository、@Service、@Controller, 2.它们分别对应数据访问层bean,业务层bean,和视图层bean。 3.目前版本中,这些注解与@Component的语义是一样的,完全通用,在Spring以后的版本中可能会给它们追 加更多的语义。 4.所以,我们推荐使用@Repository、@Service、@Controller来替代@Component。
5、@Scope:@Scope用于定义bean的作用域。
-
singleton表示在每个Spring IoC容器中一个bean定义对应一个对象实例,即Spring默认使用单例模式获取实例。
-
prototype表示一个bean定义对应多个对象实例,即非单例模式,我们常称作多例。
-
默认情况下,Spring bean 的作用域为 singleton。
@Component @Scope("prototype") public class Computer { … }
-
利用configuration.java来充当xml文件
-
@Configuration:表示这个类是配置类
-
@Bean:将下面这个类放到bean里面
@org.springframework.context.annotation.Configuration
public class Configuration {
@Bean
public Cat cat(){
return new Cat();
}
@Bean
public Dog dog(){
return new Dog();
}
@Bean
public People people(){
return new People();
}
-
测试:AnnotationConfigApplicationContext(Configuration.class);
public class MyTest { public static void main(String[] args){ ApplicationContext context=new AnnotationConfigApplicationContext(Configuration.class); People p = context.getBean(People.class); p.getDog().jiao(); p.getCat().jiao(); } }
动态代理(了解)
创建接口和impl
package com.tcc.servlet;
public interface UserServlet {
public void add();
public void delete();
public void update();
public void selete();
}
package com.tcc.servlet;
public class UserServletImpl implements UserServlet{
@Override
public void add() {
// TODO Auto-generated method stub
System.out.println("添加的方法");
}
@Override
public void delete() {
// TODO Auto-generated method stub
System.out.println("删除的方法");
}
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("更新的方法");
}
@Override
public void selete() {
// TODO Auto-generated method stub
System.out.println("查询的方法");
}
}
创建代理类和实现动态代理的方法(工具类)
package com.tcc.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.tcc.entity.User;
import com.tcc.servlet.UserServlet;
//利用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler{
private Object target;
//调用set方法设置要代理的对象
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 proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result = method.invoke(target, args);
logger(method.getName());
return result;
}
public void logger(String msg){
System.out.println("执行了"+msg+"方法");
}
}
测试:
package com.tcc.test;
import com.tcc.proxy.ProxyInvocationHandler;
import com.tcc.servlet.UserServlet;
import com.tcc.servlet.UserServletImpl;
public class MyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//真实角色
UserServlet userServlet = new UserServletImpl();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//设置要代理的对象
pih.setTarget(userServlet);
//动态生成代理类
UserServlet proxy = (UserServlet) pih.getProxy();
proxy.delete();
}
}
AOP
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方 式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个 热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑 的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高 了开发的效率。
AOP 中包含许多新的概念与术语,说明如下:
1) 切面 (Aspect):切面是系统中抽象出来的的某一个功能模块。
2) 连接点 (Joinpoint):程序执行过程中某个特定的点,如调用某方法或者处理异常时。在SpringAOP中,连接点总是代表某个方法的执行。
3) 通知 (Advice):通知是切面的具体实现,是放置“切面代码”的类。
4) 切入点 (Pointcut):多个连接点组成一个切入点,可以使用切入点表达式来表示。
5) 目标对象 (Target Object):包含一个连接点的对象,即被拦截的对象。
6) AOP代理 (AOP Proxy):AOP框架产生的对象,是通知和目标对象的结合体。
7) 织入 (Weaving):将切入点和通知结合的过程称为织入。
导入jar包
方式一:使用spring的API接口
1、创建接口和方法
2、创建log包,BeforeLog类实现(MethodBeforeAdvice类)和AfterLog类实现(AfterReturningAdvice类)。
package com.tcc.log;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class BeforeLog implements MethodBeforeAdvice{
@Override
//method(arg0): 要执行目标的方法
//args(arg1): 参数
//target(arg2): 目标对象
public void before(Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法准备执行");
}
}
package com.tcc.log;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class AfterLog implements AfterReturningAdvice{
@Override
//resultValue(arg0): 方法的返回值
//method(arg1): 要执行目标的方法
//args(arg2): 参数
//target(arg3): 目标对象
public void afterReturning(Object resultValue, Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法执行完毕,返回值为:"+resultValue);
}
}
将接口和log里的两个类添加到beans
在配置文件中添加aop约束
<?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-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
</beans>
添加Bean
<bean id="userServce" class="com.tcc.servlet.UserServiceImpl"/>
<bean id="beforeLog" class="com.tcc.log.BeforeLog"/>
<bean id="afterLog" class="com.tcc.log.AfterLog"/>
添加切面(方法一)
<!-- 方式一:使用原生spring API接口 -->
<!-- 配置aop需要导入aop的约束 -->
<aop:config>
<!-- 切入点: execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?) -->
<aop:pointcut expression="execution(* com.tcc.servlet.UserServiceImpl.*(..))" id="pointcut"/>
<!-- 执行环绕增加 -->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
测试:
package com.tcc.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tcc.servlet.UserService;
public class MyTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口
UserService userService = context.getBean(UserService.class);
userService.add();
}
}
方式二:自定义实现AOP
创建com.tcc.diyLog包,创建Diy
package com.tcc.diyLog;
public class DiyPointCut {
public void before(){
System.out.println("===============方法执行前=================");
}
public void after(){
System.out.println("================方法执行后================");
}
}
在applicationContext.xml中写入aop
<!-- 方式二:自定义实现AOP -->
<bean id="diy" class="com.tcc.diyLog.DiyPointCut"/>
<bean id="userServce" class="com.tcc.servlet.UserServiceImpl"/>
<bean id="beforeLog" class="com.tcc.log.BeforeLog"/>
<bean id="afterLog" class="com.tcc.log.AfterLog"/>
<aop:config>
<!-- 自定义切面:ref要引用的类 -->
<aop:aspect ref="diy">
<!-- 切入点 -->
<aop:pointcut expression="execution(* com.tcc.servlet.UserServiceImpl.*(..))" id="pointcut"/>
<!-- 通知 method:方法名-->
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
方式三:注解实现AOP
创建AnnocationPointCut类
1、@Aspect:将当前类定义为切面
2、@Before(“execution(* com.tcc.servlet.UserService.*(…))”):在这个类方法执行前执行下面的方法
3、@After(“execution(* com.tcc.servlet.UserService.*(…))”):在这个类方法执行后执行下面的方法
package com.tcc.diyLog;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//使用注解定义切面
@Aspect
public class AnnocationPointCut {
@Before("execution(* com.tcc.servlet.UserService.*(..))")
public void before(){
System.out.println("===============方法执行前=================");
}
@After("execution(* com.tcc.servlet.UserService.*(..))")
public void after(){
System.out.println("================方法执行后================");
}
}
优化:
@Pointcut("execution(* com.tcc.servlet.UserService.*(..))")
public void p1(){};
package com.tcc.diyLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
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 AnnocationPointCut {
@Pointcut("execution(* com.tcc.servlet.UserService.*(..))")
public void p1(){};
@Before("p1()")
public void before(){
System.out.println("===============方法执行前=================");
}
@After("p1()")
public void after(){
System.out.println("================方法执行后================");
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点:
@Around("p1()")
public void around(ProceedingJoinPoint pj) throws Throwable{
System.out.println("环绕前");
//执行方法 方法上面是前置,方法下面的是后置
Object proceed = pj.proceed();
//获得签名
Signature signature = pj.getSignature();
System.out.println(signature);
System.out.println("环绕后");
}
}
或:(不常用)
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点:
@Around("execution(* com.tcc.servlet.UserService.*(..))")
public void around(ProceedingJoinPoint pj) throws Throwable{
System.out.println("环绕前");
//执行方法
Object proceed = pj.proceed();
//获得签名
Signature signature = pj.getSignature();
System.out.println(signature);
System.out.println("环绕后");
}
结果:
环绕前
===============方法执行前=================
查询了用户
void com.tcc.servlet.UserService.selete()
环绕后
================方法执行后================
applicationContext.xml配置
<!-- 方式三:使用注解 -->
<bean id="annocationPointCut" class="com.tcc.diyLog.AnnocationPointCut"/>
<!-- 开启注解支持 jdk(默认):proxy-target-class="false"
cglib:proxy-target-class="true"-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
execution
在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点"
例如定义切入点表达式 execution (* com.sample.service.impl….(…))
execution()是最常用的切点函数,其语法如下所示:
整个表达式可以分为五个部分:
1、execution(): 表达式主体。
2、第一个星号:表示返回类型,*号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
4、第二个星号:表示类名,*号表示所有的类。
5、*(…):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
**execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?) 除了返回类型模式、方法名模式和参数模式外,其它项都是可选的。**与其直接讲解该方法的使用规则,还不如通过一个个具体的例子进行理解