Spring框架
概述
Spring框架可以通过注解或配置生成对象(一般是Bean对象),进行面向切面编程等.
Spring框架至少需要的包
pom.xml:
<properties>
<spring-version>4.3.9.RELEASE</spring-version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>compile</scope>
</dependency>
<!-- Spring核心模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-version}</version>
</dependency>
<!-- 提供与AspectJ的集成 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
将这些包复制到lib文件夹下,并添加到build path中,接下来才能使用Spring框架.
aspectjweaver包用于注解方式实现AOP
配置Spring框架及装配对象
eclipse中Spring默认配置文件是在src文件夹的applicationContext.xml文件.
IDEA中用maven创建的webapp则应放在resource文件夹:
applicationContext.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="test"></context:component-scan>
<!-- 开启代理模式,打开Spring对AOP的扫描 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean name="p" class="test.Part"></bean><!-- 装配bean对象,name指定生成对象的名称,class指定对象的类 -->
<bean name="t" class="test.Test">
<property name="name" value="this is name"/>
<property name="p" ref="p"></property><!-- 依赖注入 -->
</bean>
</beans>
需要注意的是要为对象设置的值如果是private需要类有getter和setter方法
xmlns表示声明xml命名空间
xmlns="http://www.springframework.org/schema/beans"是默认命名空间
xsi="http://www.w3.org/2001/XMLSchema-instance"是标准命名空间
xsi:schemaLocation为xsi指定具体的schema文件,对于指定的schema文件,eclipse会从默认位置寻找,如果找不到则联网查找。如果没有联网,也可以自己指定文件位置:点击windows==》preferences==》xml==》xmlcatalog==》add,选择文件即可。
创建对象的三种方式
<!-- 创建方式1:空参构造创建 -->
<bean name="user1" class="cn.example.bean.User"
init-method="init" destroy-method="destory" ></bean>
<!-- 创建方式2:静态工厂创建 调用UserFactory的createUser方法创建名为user2的对象.放入容器 -->
<bean name="user2"
class="cn.example.UserFactory"
factory-method="createUser" ></bean>
<!-- 创建方式3:实例工厂创建
调用UserFactory对象的createUser2方法创建名为user3的对象.放入容器-->
<bean name="user3"
factory-bean="userFactory"
factory-method="createUser2" ></bean>
<!-- 声明工厂bean -->
<bean name="userFactory"
class="cn.example.UserFactory"></bean>
</beans>
public class UserFactory {
public static User createUser(){
System.out.println("静态工厂创建User");
return new User();
}
public User createUser2(){
System.out.println("实例工厂创建User");
return new User();
}
}
bean对象属性注入
1 set方法注入
假设我有一个User对象,想通过set方法注入,那么在User中我们首先要提供set方法
public class User {
private String username;
public void setUsername(String username) {
this.username = username;
}
public void test() {
System.out.println(username);
}
}
<bean id="user" class="com.boss.domain.User">
<property name="username" value="张三" />
</bean>
2 构造方法注入
假设我有一个User1,User1中有一个变量叫做username,我希望通过构造方法给它注入值,那么在User1中提供相应的构造方法即可
public class User1 {
private String username;
//构造方法
public User1(String username) {
this.username = username;
}
public void test() {
System.out.println(username);
}
}
<bean id="user1" class="com.boss.domain.User1">
<constructor-arg name="username" value="李四" />
</bean>
3 p名称空间注入
假设我有一个User2对象,User2中有一个username属性,我为该属性提供了set方法,我们来看看如何在配置文件中通过p名称空间进行注入
<?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.xsd">
<bean id="user2" class="com.boss.domain.User2" p:username="王五" />
</beans>
复杂属性注入
1.对象注入
使用ref
<bean id="userDao" class="com.boss.dao.imp.UserDaoimpl" />
<bean id="userService" class="com.boss.service.imp.UserServiceImpl">
<property name="userDaoImpl" ref="userDao" />
</bean>
2 数组注入&List集合注入&Map注入&Properties注入
public class User3 {
private String[] names;
private List<String> list;
private Map<String, String> map;
private Properties properties;
public void setNames(String[] names) {
this.names = names;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void test() {
StringBuffer sb1 = new StringBuffer();
for (String name : names) {
sb1.append(name).append(",");
}
StringBuffer sb2 = new StringBuffer();
for (String s : list) {
sb2.append(s).append(",");
}
StringBuffer sb3 = new StringBuffer();
Set<String> keySet = map.keySet();
for (String s : keySet) {
sb3.append("key:" + s + ";value:" + map.get(s)).append(",");
}
System.out.println(sb1.toString());
System.out.println(sb2.toString());
System.out.println(sb3.toString());
System.out.println(properties.getProperty("username"));
}
}
<bean id="user3" class="com.boss.domain.User3">
<property name="names">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<property name="list">
<list>
<value>足球</value>
<value>篮球</value>
<value>乒乓球</value>
</list>
</property>
<property name="map">
<map>
<entry key="username" value="张三" />
<entry key="password" value="123" />
</map>
</property>
<property name="properties">
<props>
<prop key="username">赵六</prop>
</props>
</property>
</bean>
对象的获取
在需要用对象的地方通过此方法获取即可
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"applicationContext.xml"}//读取配置文件
);
Test t = (Test)context.getBean("t");//获取对象
注解方式配置对象及对象获取
配置类:
//指定此类为配置类
@Configuration
public class myFactory {
//以注解方式配置对象,指定对象名为t2
@Bean(name="t2")
public Test buikdTest() {
Test t = new Test();
t.setName("this is test");
t.setP(new Part());//设置各个属性
return t;
}
}
对象的获取
ApplicationContext context = new AnnotationConfigApplicationContext(myFactory.class);
Test t = (Test) context.getBean("t2");//注解方式获取对象
@Autowired注解自动装配对象
需先在Spring配置文件中开启注解扫描.
创建AutowiredTest :
public class AutowiredTest {
private int a;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
配置该类对象:
<bean name="autowiredTest" class="test.AutowiredTest">
<property name="a" value="3"/>
</bean>
也可以用注解来配置:
@Configuration
public class myFactory {
@Bean(name = "autowiredTest2")
public AutowiredTest buildAutowiredTest(){
AutowiredTest autowiredTest = new AutowiredTest();
autowiredTest.setA(4);
return autowiredTest;
}
}
创建Test:
public class Test {
public int a;
@Autowired
//@Qualifier("autowiredTest2")//指定装配的对象名,不指定则默认为autowiredTest
private AutowiredTest autowiredTest;
public AutowiredTest getAutowiredTest() {
return autowiredTest;
}
public void setAutowiredTest(AutowiredTest autowiredTest) {
this.autowiredTest = autowiredTest;
}
}
这样Test中就自动装配了autowiredTest属性实例.但需要把Test交给Spring容器,不能直接new Test(),否则装配不成功,autowiredTest为null.实际中往往班Test类标识成@Controller,@Service等.
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public boolean checkPwd(String uname,String upwd){
System.out.println(userDao.findById(1).getName());
System.out.println(userDao.findByName("aa"));
User user=userDao.findById(1);
if (uname.equals(user.getName())&&upwd.equals(user.getPassword())){
return true;
} else {
return false;
}
}
}
@Autowired
private UserService userService;//自动装配容器内的UserServiceImpl对象
AOP
AOP可实现在需要的方法执行前后切入另一些方法,一般是一些服务层的服务,如在用户登录、退出或切入登录日志.
首先应了解AOP的通配符,以匹配需要切入的方法。
*:匹配一个任意元素
…:匹配任意的多个元素,但在表示类时必须和 *一起使用,在表示方法参数时则不用。
+:根在类名后面,表示匹配该类的继承和扩展类,也匹配该类本身。
“. .* ” 表示匹配该包和子包下所有的类。
“.*”则表示匹配该包下所有方法。
通过注解方式实现AOP(未解决)
首先在Spring配置文件中的Beans标签下加上
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
在xsi:schemaLocation中加上
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
加上以下标签:
<!-- 开启注解扫描 -->
<context:component-scan base-package="test"></context:component-scan>
<!-- 开启代理模式,打开Spring对AOP的扫描 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
新建切面方法类,里面写需要切入的方法
@Aspect
public class AOPTest {
@Pointcut("execution(* *.Test.Runing(int))")//定义切点
public void whileruning() {
System.out.println("is runing");
}
@Before("execution(* *.Test.Runing(int))")//在方法执行之前切入
public void beforruning() {
System.out.println("before runing");
}
@AfterReturning//在方法执行之后切入
public void after() {
System.out.println("after runing");
}
}
配置对象:
<!-- 注解方式实现AOP,定义通知内容,也就是切入点执行前后需要做的事情 -->
<bean name="aoptest" class="test.AOPTest"></bean>
<!-- 定义被代理者 -->
<bean name="t" class="test.Test">
<property name="name" value="this is name"/>
<property name="p" ref="p"></property><!-- 依赖注入 -->
</bean>
但是以上方法经测无效,目前还未解决.
通过配置文件方式实现AOP
在Spring配置文件的beans根标签元素中加上:
<!-- 通过config标签实现AOP -->
<aop:config>
<!--aoptest是一个对象,里面定义了需要切入的方法-->
<aop:aspect ref="aoptest">
<aop:pointcut id="mypointcut" expression="execution(* *.Test.Runing(..))"/>
<aop:before method="beforeruning" pointcut="execution(* *.Test.Runing(..))"/>
<aop:after method="after" pointcut-ref="mypointcut"/>
<!-- <aop:around method="around" pointcut-ref="mypointcut"/> -->
</aop:aspect>
</aop:config>